开发者

HTTP digest authentication with HttpUrlConnection

开发者 https://www.devze.com 2023-01-20 23:40 出处:网络
I am trying to connect to the Tomcat Web Server on my machine using a digest authentication. I am using the memory realm of tomcat. Here is how the server is configured:

I am trying to connect to the Tomcat Web Server on my machine using a digest authentication. I am using the memory realm of tomcat. Here is how the server is configured:

1) In server.xml:

<Realm className="org.apache.catalina.realm.MemoryRealm" digest="MD5" />

2) In tomcat-users.xml

<user username="testuser" password="81dc9bdb52d04dc20036dbd8313ed055" roles="test"/>

3) In web.xml of my web project:

<auth-method>DIGEST</auth-method>

As you can see I have specified as a digest method "MD5" and I have encryped the password using the digest.sh of Tomcat.

Here is my code on the client side:

private static void testGet() throws IOException {

    // Create a URL
    URL test = new URL("http://localhost:8080/TestWebProject/TestServlet");

    // Open a connection to the URL
    HttpURLConnection conn = (HttpURLConnection) test.openConnection();

    MessageDigest md5 = null;
    try {
      md5 = MessageDigest.getInstance("MD5");
    } catch(NoSuchAlgorithmException e) {
      e.printStackTrace();
    }

    // Digest password using the MD5 algorithm
    String password = "1234";
    md5.update(password.getBytes());
    String digestedPass = digest2HexString(md5.digest());

    开发者_如何学Python// Set header "Authorization"
    String credentials = "testuser:" + digestedPass;
    conn.setRequestProperty("Authorization", "Digest " + credentials);

    // Print status code and message
    System.out.println("Test HTTP GET method:");
    System.out.println("Status code: " + conn.getResponseCode());
    System.out.println("Message: " + conn.getResponseMessage());
    System.out.println();

}

private static String digest2HexString(byte[] digest)
{
   String digestString="";
   int low, hi ;

   for(int i=0; i < digest.length; i++)
   {
      low =  ( digest[i] & 0x0f ) ;
      hi  =  ( (digest[i] & 0xf0)>>4 ) ;
      digestString += Integer.toHexString(hi);
      digestString += Integer.toHexString(low);
   }
   return digestString ;
}

I think that my client side code is ok and the configuration of the server, too. Though the server keeps sending me the status code 401 with message "Unauthorized". As I am not an experienced java developer, I want to ask if anyone has idea or sees an error in my implementation.

Thank you in advance!


Digest authentication is far more complex than just sending username:password (that is actually Basic authentication... and the username:password tuple needs to be Base64 encoded!).

You can read all about digest here.

If you're not required to use HttpUrlConnection take a look at these two projects:

  • Async Http Client (more mature)
  • Hotpotato (mine)

Both of them already support Digest (and other useful stuff) out of the box.


HttpUrlConnection is OK for simple jobs, but if you want something with more advanced features (like digest authentication), I'd recommend Commons HTTP Client.


I am able to get it done working following code, please let me know if i am missing something;

        DefaultHttpClient httpclient = new DefaultHttpClient();

        ResponseHandler<String> responseHandler = new BasicResponseHandler();

        httpclient.getCredentialsProvider().setCredentials(
                new AuthScope("localhost", 8080), 
                new UsernamePasswordCredentials("username", "password"));   

        HttpGet httpget = new HttpGet(urlStr);
         System.out.println("executing request" + httpget.getRequestLine());

        String response = httpclient.execute(httpget, responseHandler);
        System.out.println("Response :: " + response);


Use the following code, it works if your server doesn't require an 'opaque' return.

import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;

CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
                new UsernamePasswordCredentials(username, password));
        CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultCredentialsProvider(credsProvider)
                .build();


HttpResponse response = httpClient.execute(get);


Strangely enough Digest authentication works natively on jdk with this code while Basic auth does not:

Authenticator.setDefault(new Authenticator() {

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {

        return new PasswordAuthentication (
            "username",
            "password".toCharArray()
        );
    }
});
0

精彩评论

暂无评论...
验证码 换一张
取 消