使用 URLConnection 进行摘要式身份验证

Posted

技术标签:

【中文标题】使用 URLConnection 进行摘要式身份验证【英文标题】:Digest authentication using URLConnection 【发布时间】:2010-11-25 16:06:57 【问题描述】:

我正在实施单点登录功能,以便使用摘要身份验证自动登录附属的 https 网站。目前我的代码是

URL url = new URL(protocol, ip, port, path);
URLConnection connection = url.openConnection(Proxy.NO_PROXY);
connection.connect();

if (connection != null && connection.getHeaderFields() != null) 
    if (connection.getHeaderFields().get(AUTHENTICATE_RESPONSE_HEADER) != null) 
        Map<String, String> authenticateParameters = identifyAuthentication(connection);

        String ha1 = calculateMD5(username + ":" + authenticateParameters.get("realm") + ":" + password);
        String ha2 = calculateMD5("GET" + ":" + path);
        String response = calculateMD5(ha1 + ":" + 
            authenticateParameters.get("nonce") + ":" +
            "00000001" + ":" +
            authenticateParameters.get("qop") + ":" +
            ha2);

            String authorizationRequest = authenticateParameters.get("challenge") + " " + 
                    "username=" + username + ", " +
                    "realm=" + authenticateParameters.get("realm") + ", " +
                    "nonce=" + authenticateParameters.get("nonce") + ", " +
                    "uri=" + path + ", " +
                    "qop=" + authenticateParameters.get("qop") + ", " +
                    "nc=" + "00000001" + ", " +
                    "response=" + response + ", " +
                    "opaque=" + authenticateParameters.get("opaque");

            connection.setAllowUserInteraction(true);
            connection.addRequestProperty(AUTHENTICATION_REQUEST_PROPERTY, authorizationRequest);
            connection.getHeaderFields();
    

问题是我得到了

java.lang.IllegalStateException: Already connected
    at java.net.URLConnection.addRequestProperty(URLConnection.java:1061)
    at sun.net.www.protocol.http.HttpURLConnection.addRequestProperty(HttpURLConnection.java:2016)
    at com.ibm.net.ssl.www2.protocol.https.a.addRequestProperty(a.java:49)

我想这是有道理的,但对我没有帮助。我将如何创建用于在此处登录的请求/响应(并最终获得 sessionId)?

提前致谢。

【问题讨论】:

我们能看到完整的堆栈跟踪吗?我不确定你方法中的哪一行失败了。 已添加 - 感谢您抽出宝贵时间。 【参考方案1】:

当连接请求标头已经连接(您已经发送了请求标头)时,您不能修改它。您必须为第二个请求建立新连接。

例如

connection = url.openConnection(Proxy.NO_PROXY);
connection.addRequestProperty(AUTHENTICATION_REQUEST_PROPERTY, authorizationRequest);
connection.getHeaderFields();

然后您可以从标头中获取 sessionId 或更确切地说是 cookie。

使用 apache HttpClient 的 Digest 功能可能更容易:http://hc.apache.org/httpclient-3.x/authentication.html

【讨论】:

建立新连接会返回与以前相同的 401 回复。 但是你没有得到原来的例外吗?您的授权请求可能不正确。响应头是什么? 最后我使用 HttpClient 完成了这项工作。更简单更容易! 这对你有用!你为什么不喜欢接受答案?

以上是关于使用 URLConnection 进行摘要式身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 Zombie.js 进行摘要式身份验证

使用 Java 进行基本和摘要式访问身份验证

Apache http 客户端示例无法进行摘要式身份验证

为啥在 Django 中需要基本或摘要式身份验证?

摘要身份验证返回未经授权的

具有摘要式身份验证的 ASP.Net Web API