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

下面是我在握手失败时使用的代码:
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
请帮助进行代码修正。
发布于 2021-02-23 08:20:55
在postman中,您可以将请求导出到代码段(请参阅https://learning.postman.com/docs/sending-requests/generate-code-snippets/方法)。
在您的示例中,使用OkHttp客户端的java代码片段将是:
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__、nonce和uri。)
要计算response值,您可以在https://en.wikipedia.org/wiki/Digest_access_authentication中看到公式(用于MD5)。
在上面的代码中,使用SHA256而不是MD5计算如下:
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)
= 6d46e1187d1e79c88241d4ae0e57eda1cd572dfb027ce9eded02aea499f15695https://stackoverflow.com/questions/66328647
复制相似问题