java - 使用 HTTP Commons Client 的基本身份验证

标签 java apache-commons-httpclient

我正在查看此链接并尝试向服务器发送请求

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

public class Test {
    public static void main(String[] args) throws ClientProtocolException, IOException {

        DefaultHttpClient httpClient;
        URL url = new URL("https://9.5.127.34:443");
        httpClient = getSSLHttpClient(url);
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                new AuthScope("https://9.5.127.34", AuthScope.ANY_PORT),
                new UsernamePasswordCredentials("root", "passw0rd"));


         httpClient.setCredentialsProvider(credsProvider);


        HttpGet httpget = new HttpGet("https://9.5.127.34/powervc/openstack/volume/v1/115e4ad38aef463e8f99991baad1f809//volumes/3627400b-cd98-46c7-a7e2-ebce587a0b05/restricted_metadata");
        HttpResponse response = httpClient.execute(httpget);
        BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        String line = "";
        while ((line = rd.readLine()) != null) {

            System.out.println(line);

            }   
        }

但它给我的错误是

Authentication required

请告诉我我做错了什么。提前致谢

最佳答案

也许您应该尝试像这里解释的那样抢先发送身份验证参数:http://hc.apache.org/httpclient-legacy/authentication.html - 但我不确定这是否与您的版本有关。

Mat Mannion (@MatMannion) 描述了一种更常见的方法,应该适用于当前版本:Preemptive Basic authentication with Apache HttpClient 4

基本上,您只需要添加一个包含 key 的 HTTP header 字段:“authorization”和用户名和密码的 base64 编码字符串(组合在一起,然后进行 base64 编码)或@Jonathan 或@AdamBatkin 提供的方式在同一个线程中(上面链接)


@编辑:

在有一些空闲时间后,我将您的示例代码放入 Netbeans(是的,我想更熟悉 NB)并构建了一个简单的 jetty 服务器演示,它使用 SSL 和基本身份验证以及一个 Apache HttpClient 来调用一个简单的 hello world servlet 来展示客户端需要如何定义 SSL 和基本身份验证。进一步请注意,一些代码取自官方文档,并且 keystore 和信任库的设置如解释的那样 here .

请在下面找到该项目的完整代码(除了二进制的 keystore )(也许其他人也可能会觉得它有用)。

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>at.rovo.test</groupId>
  <artifactId>HttpClientExample</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>HttpClientExample</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!-- Client -->
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.3</version>
      <type>jar</type>
    </dependency>
    <!-- Server -->
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-server</artifactId>
      <version>9.1.0.M0</version>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-security</artifactId>
      <version>9.1.0.M0</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>org.eclipse.jetty</groupId>
      <artifactId>jetty-servlet</artifactId>
      <version>9.1.0.M0</version>
      <type>jar</type>
    </dependency>
  </dependencies>
</project>

JettyServer.java

package at.rovo.test.httpclient;

import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.security.Constraint;

public class JettyServer 
{
    private String REALM;

    public static void main( String[] args ) throws Exception
    {
        new JettyServer();
    }

    public JettyServer() throws Exception
    {
        Server server = new Server(8080);
        server.addConnector(this.getSslChannelConnector(server));
        server.setStopAtShutdown(true);

        // create the context handler for the server        
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        context.setClassLoader(Thread.currentThread().getContextClassLoader());
        // attach the security handler to it that has basic authentication
        context.setSecurityHandler(this.getSecurityHandler());

        server.setHandler(context);
        // define the processing servlet
        context.addServlet(new ServletHolder(new ProcessingServlet()), "/process");

        server.start();
        server.join();
    }

    private Connector getSslChannelConnector(Server server)
    {
        try
        {           
            String keyStore = this.getClass().getResource("/serverKey.jks").toURI().getPath();

            SslConnectionFactory sslConnFactory = new SslConnectionFactory();
            sslConnFactory.getSslContextFactory().setKeyStorePath(keyStore);
            sslConnFactory.getSslContextFactory().setKeyStorePassword("keystorePW");
            sslConnFactory.getSslContextFactory().setKeyManagerPassword("jettyPW");

            HttpConfiguration config = new HttpConfiguration();
            ConnectionFactory connFactory = new HttpConnectionFactory(config);

            ServerConnector connector = new ServerConnector(server, sslConnFactory, connFactory);
            connector.setPort(8443);
            connector.setHost("localhost");
            connector.setIdleTimeout(30000);
            return connector;
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return null;
    }

    private SecurityHandler getSecurityHandler() throws Exception 
    {
        // add authentication
        Constraint constraint = new Constraint(Constraint.__BASIC_AUTH,"user");
        constraint.setAuthenticate(true);
        constraint.setRoles(new String[]{"user","admin"});

        // map the security constraint to the root path.
        ConstraintMapping cm = new ConstraintMapping();
        cm.setConstraint(constraint);
        cm.setPathSpec("/*");

        // create the security handler, set the authentication to Basic
        // and assign the realm.
        ConstraintSecurityHandler csh = new ConstraintSecurityHandler();
        csh.setAuthenticator(new BasicAuthenticator());
        csh.setRealmName(REALM);
        csh.addConstraintMapping(cm);

        // set the login service
        csh.setLoginService(getHashLoginService());

        return csh;
    }

    private HashLoginService getHashLoginService() throws Exception 
    {
        // load the authentication data from a simple property file
        HashLoginService hls = new HashLoginService();
        hls.setName(REALM);
        hls.setConfig(this.getClass().getResource("/realm.properties").toURI().toString());
        hls.setRefreshInterval(0);
        return hls;
    }
}

ProcessingServlet.java

package at.rovo.test.httpclient;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ProcessingServlet extends HttpServlet
{
    public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException 
    {
        response.setContentType("text/html");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().println("<h1>Hello World</h1>");
        response.getWriter().println("session=" + request.getSession(true).getId());
  }
}

领域.属性

admin: admin123, admin
root: passw0rd, user

客户端.java

package at.rovo.test.httpclient;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class Client 
{
    public static void main(String[] args) throws Exception 
    {
        CloseableHttpClient httpClient;

        // SSL setup
        KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
        FileInputStream instream = new FileInputStream(new File(Client.class.getResource("/clientTrust.jks").toURI()));
        try 
        {
            trustStore.load(instream, "truststorePW".toCharArray());
        } 
        finally 
        {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom()
                .loadTrustMaterial(trustStore)
                .build();
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);


        HttpHost targetHost = new HttpHost("localhost", 8443, "https");

        // Basic Auth setup
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(
                new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                new UsernamePasswordCredentials("root", "passw0rd"));
        httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .setDefaultCredentialsProvider(credsProvider)
                .build();

        try
        {
            HttpGet httpget = new HttpGet("https://localhost:8443/process");

            System.out.println("executing request: " + httpget.getRequestLine());
            System.out.println("to target: " + targetHost);

            CloseableHttpResponse response = httpClient.execute(httpget);
            try
            {
                HttpEntity entity = response.getEntity();

                System.out.println("--------------------------------------------------");
                System.out.println(response.getStatusLine());
                if (entity != null)
                {
                    System.out.println("Response content length: "+entity.getContentLength());
                }
                BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                String line;
                while ((line = rd.readLine()) != null) 
                {
                    System.out.println(line);
                }
                EntityUtils.consume(entity);
            }
            finally
            {
                response.close();
            }
        }
        finally
        {
            httpClient.close();
        }
    }
}

请耐心等待,因为我几乎不检查错误,但这是一个快速且简单的示例,用于演示使用基本身份验证的 SSL 保护的 Apache HttpClient 的功能。

关于java - 使用 HTTP Commons Client 的基本身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19679320/

相关文章:

java - Activity 中的转换界面

java - GWT 中的双括号有多有害?

java - 单连接中的多条语句

java - HttpClientFormSubmit 获取 OAUTH 访问 token

java - HTTP Apache,ssl 身份验证在 Java 1.8 中不起作用

java - 在 SnakeYAML 中折叠单子(monad) bean

java - 从数组更新 JPanel

java - 将 Apache Commons HttpClient 日志调整为 Dropwizard

java - 使用 Commons HTTPClient 自定义 HTTP header ?

java - 如何使用 Apache HttpClient 发布 JSON 请求?