【问题标题】:Java httpClient 4.3.6 basic Authentication with complete URI and scheme具有完整 URI 和方案的 Java httpClient 4.3.6 基本身份验证
【发布时间】:2015-08-19 14:10:25
【问题描述】:

我想要什么: 发送带有抢占式基本身份验证的 GET 请求。

请求看起来像这样:

<startURL>/app/process?job=doSomething&param=value1,value2

而 startURL 始终是 https 链接,具体取决于环境。

看起来像这样: https://testABC.com https://prodABC.com

startURL 也被放置在不同环境的属性文件中。

我调查的内容: http://www.baeldung.com/httpclient-4-basic-authentication

http://www.java-tips.org/other-api-tips/httpclient/how-to-use-basic-authentication.html

http://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientPreemptiveBasicAuthentication.java

http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html

这一切都包含一个

 HttpHost targetHost = new HttpHost("hostname", portnumber, "scheme");

这是我遇到的麻烦。此方法也是唯一允许您将方案指定为“https”的方法。 一个问题是,我不知道端口号。我认为(?)我可能只为默认端口指定 -1 以使其工作,但即使除此之外我也没有主机名,只有上面提到的 startURL。我真的不想每次都解析这个额外的内容,同时我也不想添加另一个属性,只是为了主机名。

我四处挖掘,发现了这个 sn-p,看起来正是我想要的:

HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://foo.com/bar");
httpGet.addHeader(BasicScheme.authenticate(
 new UsernamePasswordCredentials("user", "password"),
 "UTF-8", false));

HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity responseEntity = httpResponse.getEntity();

来自HTTP requests with basic authentication

它给出了完整的请求 URL 并简单地添加了基本标头,不需要指定任何端口。只是现在从版本 4.2 开始不推荐使用:

Deprecated. (4.2) Use ContextAwareAuthScheme.authenticate( Credentials, HttpRequest, org.apache.http.protocol.HttpContext)

我找不到此方法返回基本身份验证标头的单个示例。它还需要一个上下文作为参数,而上面 snipped 没有。我真的不知道应该如何使用它。

那么,我想具体了解什么:

我只想设置一个包含完整链接的请求,其中包含所有内容,例如:

https://testABC.com/app/process?job=doSomething&param=value1,value2

并将其作为执行抢先式基本身份验证的请求的参数。

有什么方法可以做到这一点,而无需挖掘已弃用的方法以及它的外观如何?

【问题讨论】:

    标签: java authentication basic-authentication apache-httpclient-4.x


    【解决方案1】:

    我遇到了和你一样的问题。

    对我有用的是:

    UsernamePasswordCredentials creds = new UsernamePasswordCredentials("user", "12345");
    
    HttpGet get = new HttpGet("https://foo.bar.com/rest");
    HttpHost targetHost = new HttpHost("foo.bar.com", 443, "https");
      CredentialsProvider credsProvider = new BasicCredentialsProvider();
      credsProvider.setCredentials(
              new AuthScope(targetHost.getHostName(), targetHost.getPort()),
              creds);
      credsProvider.setCredentials(AuthScope.ANY,creds);
    
     // Create AuthCache instance
      AuthCache authCache = new BasicAuthCache();
     // Generate BASIC scheme object and add it to the local auth cache
      BasicScheme basicAuth = new BasicScheme();
      authCache.put(targetHost, basicAuth);
    
     // Add AuthCache to the execution context
      HttpClientContext context = HttpClientContext.create();
    context.setCredentialsProvider(credsProvider);
    context.setAuthCache(authCache);
    HttpResponse response = client.execute(targetHost, get, context);
    

    我找到了这个解决方案:HttpClientBuilder basic auth

    【讨论】:

    • 不会有帮助,因为 HttpHost 构造函数需要指定的端口和主机名。但如上所述,我只有 startUrl,并且明确希望避免将其解析并分解为这三个参数值。
    • 在我的情况下,虽然我发现相同的 Authorization 标头内容设置为 Base64,但以您的方式创建标头不起作用。出于某种原因,使用 httpGet.addHeader(BasicScheme.authenticate( new UsernamePasswordCredentials("user", "password"), "UTF-8", false)) 设置的 Base64 授权有效,而不是手动设置导致 401 .无论如何设置这应该像4.1.x一样简单
    • 从 stackoverflow 尝试了 serval 版本,这篇文章是唯一对我有用的。
    【解决方案2】:

    最后,我自己手动编写了标题并用它发送了东西:

        String header = "Basic ";       
        String headerValue = "username" + ":" + "password";
        String encodedHeaderValue = Base64.encodeBase64String(headerValue.getBytes());      
        String headerBasic =  header + encodedHeaderValue;
    
        Header authHeader = new BasicHeader("Authorization", headerBasic);
          ArrayList<Header> headers = new ArrayList<Header>();
          headers.add(authHeader);  
    
        ArrayList<Header> headers = getHttpHeaders();
        HttpClient client = HttpClients.custom().setDefaultHeaders(headers).build();
    
        HttpUriRequest request = RequestBuilder.get().setUri(uri).build();
        HttpResponse response = client.execute(request);
    
        int responseCode = response.getStatusLine().getStatusCode();
    

    【讨论】:

      猜你喜欢
      • 2023-04-08
      • 2016-12-19
      • 2018-08-12
      • 1970-01-01
      • 1970-01-01
      • 2017-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多