首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用基于SHA-256算法的JAVA摘要认证实现登录

如何用基于SHA-256算法的JAVA摘要认证实现登录
EN

Stack Overflow用户
提问于 2021-02-23 07:14:48
回答 1查看 1.2K关注 0票数 0

我试图在java中使用SHA-256算法实现基于Digest身份验证的登录,但没有得到多少帮助。我可以使用POSTMAN登录并获得HTTP状态代码200,但不确定POSTMAN如何在这里使用SHA-256、Postman请求配置快照和下面的实现,这会抛出SSLHandshakeException。

下面是我在握手失败时使用的代码:

代码语言:javascript
复制
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.*;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.*;

import junit.framework.Assert;

public class DigestTest {

    private static final String URL = "https://10.0.1.190/API/Web/Login";
    private static final String USER = "admin";
    private static final String PASSWORD = "testing123456";


    public static void main(String[] args) throws Exception {

        new DigestTest().run();
    }

    public void run() throws Exception {
        System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");

        HttpPost httpPost = new HttpPost(URL);

        HttpHost target
                = new HttpHost(httpPost.getURI().getHost(), 443, "https");
        CredentialsProvider credsProvider = new BasicCredentialsProvider();

        UsernamePasswordCredentials credentials
                = new UsernamePasswordCredentials(USER, PASSWORD);
        credsProvider.setCredentials(
                new AuthScope(target.getHostName(), target.getPort()),
                credentials);

        CookieStore cookieStore = new BasicCookieStore();

        CloseableHttpClient httpclient
                = HttpClients.custom().setDefaultCookieStore(cookieStore)
                        .setDefaultCredentialsProvider(credsProvider).build();

        try {

            DigestScheme digestAuth = new DigestScheme();

            digestAuth.overrideParamter("qop", "auth");
            digestAuth.overrideParamter("nc", "0");
            digestAuth.overrideParamter("cnonce", DigestScheme.createCnonce());
            digestAuth.overrideParamter("algorithm", "SHA-256");

            AuthCache authCache = new BasicAuthCache();
            authCache.put(target, digestAuth);

            HttpClientContext localContext = HttpClientContext.create();
            localContext.setAuthCache(authCache);

            CloseableHttpResponse response;

            response = httpclient.execute(target, httpPost, localContext);
            Map<String, String> wwwAuth = Arrays
                    .stream(response.getHeaders("WWW-Authenticate")[0]
                            .getElements())
                    .collect(Collectors.toMap(HeaderElement::getName,
                            HeaderElement::getValue));

            // the first call ALWAYS fails with a 401
//            Assert.assertEquals(response.getStatusLine().getStatusCode(), 401);

            digestAuth.overrideParamter("opaque", wwwAuth.get("opaque"));
            digestAuth.overrideParamter("nonce", wwwAuth.get("nonce"));
            digestAuth.overrideParamter("realm", wwwAuth.get("Digest realm"));
            Header authenticate = digestAuth.authenticate(credentials, httpPost,
                    localContext);
            httpPost.addHeader(authenticate);

            response = httpclient.execute(target, httpPost, localContext);

            // the 2nd call is the real deal
//            Assert.assertEquals(response.getStatusLine().getStatusCode(), 200);

            //System.out.println(IOUtils
              //      .toString(response.getEntity().getContent(), "utf-8"));
            System.out.println(response.getEntity().getContent().toString());

        } catch(Exception e){
            System.out.println("Exception : \n"+e);
        } finally {
            httpclient.close();
        }
    }

}

我得到的例外如下:

异常: javax.net.ssl.SSLHandshakeException:接收到致命警报: handshake_failure

请帮助进行代码修正。

EN

回答 1

Stack Overflow用户

发布于 2021-02-23 08:20:55

在postman中,您可以将请求导出到代码段(请参阅https://learning.postman.com/docs/sending-requests/generate-code-snippets/方法)。

在您的示例中,使用OkHttp客户端的java代码片段将是:

代码语言:javascript
复制
OkHttpClient client = new OkHttpClient().newBuilder()
  .build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "{}");
Request request = new Request.Builder()
  .url("https://test.it/uri")
  .method("POST", body)
  .addHeader("Authorization", 
             "Digest username=\"username\", realm=\"test\", nonce=\"nonce\", uri=\"/uri\", 
             algorithm=\"SHA-256\", 
             response=\"6d46e1187d1e79c88241d4ae0e57eda1cd572dfb027ce9eded02aea499f15695\""
  )
  .addHeader("Content-Type", "text/plain")
  .build();
Response response = client.newCall(request).execute();

(请注意,您需要用实际值替换username__、realm__、nonceuri。)

要计算response值,您可以在https://en.wikipedia.org/wiki/Digest_access_authentication中看到公式(用于MD5)。

在上面的代码中,使用SHA256而不是MD5计算如下:

代码语言:javascript
复制
HA1 = SHA256(username:realm:password) = SHA256(username:test:password) = 338c3ad443d25c378fdcdb90df9f81d42161278b8f1f03276a2d14f0803165f2
HA2 = SHA256(method:digestURI) = SHA256(POST:/uri) = fc51c21830fc2b6ffe97afe3290df89e7c2b1e287d6e373ad4282ce7fe912650
response = SHA256(HA1:nonce:HA2) = SHA256(338c3ad443d25c378fdcdb90df9f81d42161278b8f1f03276a2d14f0803165f2:nonce:fc51c21830fc2b6ffe97afe3290df89e7c2b1e287d6e373ad4282ce7fe912650)
= 6d46e1187d1e79c88241d4ae0e57eda1cd572dfb027ce9eded02aea499f15695
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66328647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档