为什么其他用户的摘要式身份验证Java HttpClient代码对我不起作用?

时间:2018-10-27 18:59:16

标签: apache-httpclient-4.x http-authentication

我需要从Java调用REST服务,并且该服务需要摘要式身份验证。使用curl --digest -c cookie.txt ...

进行测试时,调用工作正常

经过几次死胡同,我在@Ted Yang和user1107423对问题Apache HttpClient Digest authentication的回答中发现了一些有希望的伪代码。所以这就是我现在想要实现的。

到目前为止,这是我的尝试:

import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.auth.*;
import org.apache.http.client.*;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.*;
import org.apache.http.protocol.BasicHttpContext;

[...]

    private String connect(URL url, String user,
            String password) throws URISyntaxException, IOException, ClientProtocolException {
        HttpHost targetHost = new HttpHost(url.getHost(),
                url.getPort(),
                url.getProtocol());

        URI uri = url.toURI();

        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials(user,
                        password));
        httpclient = HttpClientBuilder.create()
                .setDefaultCredentialsProvider(credsProvider).build();

        AuthCache authCache = new BasicAuthCache();
        BasicScheme basicAuth = new BasicScheme();
        authCache.put(targetHost, basicAuth);

        HttpClientContext context = HttpClientContext.create();
        context.setAttribute(HttpClientContext.AUTH_CACHE, authCache);

        CookieStore cookieStore = new BasicCookieStore();
        context.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);

        @SuppressWarnings("serial")
        class AuthException extends RuntimeException {

            public final Header header;

            public AuthException(Header header) {
                this.header = header;
            }

            public String get(String key) {
                return Arrays.stream(header.getElements())
                    .filter(h -> h.getName().equals(key))
                    .findFirst()
                    .map(HeaderElement::getValue)
                    .get();
            }
        }

        BasicResponseHandler responseHandler = new BasicResponseHandler() {

            public String handleResponse(
                    HttpResponse response) throws HttpResponseException, IOException {
                if (response.getStatusLine().getStatusCode() == 401) {
                    Header header = response.getFirstHeader("WWW-Authenticate");
                    if (header != null) {
                        throw new AuthException(header);
                    }
                }
                return super.handleResponse(response);
            };
        };
        try {
            return httpclient.execute(new HttpGet(uri), responseHandler,
                    context);
        } catch (AuthException req) {
            DigestScheme digestScheme = new DigestScheme();

            String realm = req.get("Digest realm");
            digestScheme.overrideParamter("realm", realm);
            String nonce = req.get("nonce");
            digestScheme.overrideParamter("nonce", nonce);

            authCache.put(targetHost, digestScheme);

            context.setCredentialsProvider(credsProvider);
            context.setAuthCache(authCache);

            return httpclient.execute(new HttpGet(uri),
                    new BasicResponseHandler(), context);
        }
    }

问题是我在第二个HTTP调用中仍然收到401。

可能是什么原因?

更新

我还从@ user1107423的答案中添加了digestScheme.processChallenge(req.header);,但这没有什么不同。

这是httpclient连线日志的最新相关部分

2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] .i.c.DefaultHttpClientConnectionOperator : Connection established 192.168.7.26:51130<->209.80.40.145:443
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] o.a.http.impl.execchain.MainClientExec   : Executing request GET /contact/rets/login?rets-version=RETS/1.7.2 HTTP/1.1
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] o.a.http.impl.execchain.MainClientExec   : Target auth state: FAILURE
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] o.a.http.impl.execchain.MainClientExec   : Proxy auth state: UNCHALLENGED
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.headers                  : http-outgoing-1 >> GET /contact/rets/login?rets-version=RETS/1.7.2 HTTP/1.1
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.headers                  : http-outgoing-1 >> Host: xxxxx.org
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.headers                  : http-outgoing-1 >> Connection: Keep-Alive
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.headers                  : http-outgoing-1 >> User-Agent: Apache-HttpClient/4.5.6 (Java/1.8.0_60)
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.headers                  : http-outgoing-1 >> Cookie: JSESSIONID=01681A32C72B20D1BE4BCFE17F5A015D
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.headers                  : http-outgoing-1 >> Accept-Encoding: gzip,deflate
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 >> "GET /contact/rets/login?rets-version=RETS/1.7.2 HTTP/1.1[\r][\n]"
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 >> "Host: **xxxxxxxxxxx**[\r][\n]"
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 >> "Connection: Keep-Alive[\r][\n]"
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 >> "User-Agent: Apache-HttpClient/4.5.6 (Java/1.8.0_60)[\r][\n]"
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 >> "Cookie: JSESSIONID=01681A32C72B20D1BE4BCFE17F5A015D[\r][\n]"
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 >> "Accept-Encoding: gzip,deflate[\r][\n]"
2018-10-27 13:12:58.408 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 >> "[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "HTTP/1.1 401 Unauthorized[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "Server: Apache-Coyote/1.1[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "Set-Cookie: JSESSIONID=01681A32C72B20D1BE4BCFE17F5A015D; Path=/contact[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "MIME-Version: 1.0[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "Cache-Control: private[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "RETS-Version: RETS/1.7.2[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "WWW-Authenticate: Digest realm="xxxxxxxxxx",qop="auth",nonce="b13fbc2aa074
9a42d37610c424e5d288", opaque="027f66646cdae"[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "Content-Type: text/html;charset=utf-8[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "Content-Length: 954[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "Date: Sat, 27 Oct 2018 20:12:56 GMT[\r][\n]"
2018-10-27 13:12:58.437 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "[\r][\n]"
2018-10-27 13:12:58.438 DEBUG 23768 --- [           main] org.apache.http.wire                     : http-outgoing-1 << "<html><head><title>Apache Tomcat/6.0.35 - Error report</title><style><!--H1 {fo

1 个答案:

答案 0 :(得分:0)

原因显然是所有现有示例都不需要客户端将401响应中的opaquenonce值复制到第二个请求。