Java 使用 HttpUrlConnection 进行 HTTP 摘要身份验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4008545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 08:17:27  来源:igfitidea点击:

HTTP digest authentication with HttpUrlConnection

java

提问by user485624

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:

我正在尝试使用摘要身份验证连接到我机器上的 Tomcat Web 服务器。我正在使用tomcat的内存领域。以下是服务器的配置方式:

1) In server.xml:

1) 在 server.xml 中:

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

2) In tomcat-users.xml

2) 在 tomcat-users.xml 中

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

3) In web.xml of my web project:

3)在我的web项目的web.xml中:

<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.

如您所见,我已将摘要方法指定为“MD5”,并使用 Tomcat 的digest.sh 对密码进行了加密。

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());

    // 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.

我认为我的客户端代码没问题,服务器的配置也是如此。尽管服务器不断向我发送状态代码 401,并显示消息“未授权”。由于我不是经验丰富的 Java 开发人员,我想问一下是否有人对我的实现有想法或看到错误。

Thank you in advance!

先感谢您!

回答by biasedbit

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

摘要式身份验证远比发送复杂得多username:password(实际上是基本身份验证……并且username:password元组需要进行 Base64 编码!)。

You can read all about digest here.

您可以在此处阅读有关摘要的所有信息。

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

如果您不需要使用,HttpUrlConnection请查看这两个项目:

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

他们都已经开箱即用地支持 Digest(和其他有用的东西)。

回答by Mike Baranczak

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

HttpUrlConnection 适用于简单的工作,但如果您想要具有更高级功能(如摘要身份验证)的东西,我建议使用Commons HTTP Client。

回答by Maths

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);

回答by Yandrapu

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

使用以下代码,如果您的服务器不需要 '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);

回答by ron190

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

奇怪的是,摘要式身份验证使用此代码在 jdk 上本地工作,而基本身份验证则不:

Authenticator.setDefault(new Authenticator() {

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {

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