Java 使用 HTTP Commons 客户端的基本身份验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19679320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Basic Authentication using HTTP Commons Client
提问by The_Lost_Avatar
I am looking at this link an am trying to send requests to the server
我正在查看此链接并尝试向服务器发送请求
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html
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);
}
}
But it is giving me error as
但它给了我错误
Authentication required
Please tell me what I am doing wrongly. Thanx in Advance
请告诉我我做错了什么。提前致谢
采纳答案by Roman Vottner
Maybe you should try to send the authentication parameters preemptively like explained here: http://hc.apache.org/httpclient-legacy/authentication.html- but I'm not sure if this relates to your version.
也许您应该尝试像这里解释的那样抢先发送身份验证参数:http: //hc.apache.org/httpclient-legacy/authentication.html- 但我不确定这是否与您的版本有关。
Mat Mannion (@MatMannion) described probably a more common method, which should work with the current version: Preemptive Basic authentication with Apache HttpClient 4
Mat Mannion (@MatMannion) 描述了可能更常见的方法,它应该适用于当前版本:Preemptive Basic authentication with Apache HttpClient 4
Basically you just need to add a HTTP-header field containing the key: "authorization" and a base64 encoded string of the username and the password (combined together and then base64 encoded) or the way @Jonathan or @AdamBatkin presented it in the same thread (linked above)
基本上,您只需要添加一个包含密钥的 HTTP 标头字段:“授权”和用户名和密码的 base64 编码字符串(组合在一起,然后进行 base64 编码)或 @Jonathan 或 @AdamBatkin 以相同的方式呈现它的方式线程(上面链接)
@edit:
@编辑:
After having had a bit of spare-time I took your example code and throw it into Netbeans (yeah, I want to get a bit more familiar with NB) and built a simple jetty server demo which uses SSL and basic auth and an Apache HttpClient to invoke a simple hello world servlet to showcase how the client needs to define SSL and basic auth. Note further that some of the code was taken from the official docs and the keystore as well as the truststore are setup like explained here.
在有一点空闲时间后,我把你的示例代码扔进了 Netbeans(是的,我想更熟悉 NB)并构建了一个简单的码头服务器演示,它使用 SSL 和基本身份验证以及一个 Apache HttpClient调用一个简单的 hello world servlet 来展示客户端需要如何定义 SSL 和基本身份验证。此外,值得注意的是一些代码是从官方文档拍摄和密钥库以及与信任是建立像解释这里。
Below please find the complete code (except the keystores which are binary) of the project (maybe someone other might find it useful too).
请在下面找到项目的完整代码(除了二进制的密钥库)(也许其他人也可能觉得它很有用)。
pom.xml
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
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
处理Servlet.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());
}
}
realm.properties
领域.properties
admin: admin123, admin
root: passw0rd, user
Client.java
客户端.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();
}
}
}
Bear with me as I'm hardly checking for errors, but this is a quick&dirty example to demonstrate just the functionality of an SSL-secured Apache HttpClient that uses basic authentication.
请耐心等待,因为我几乎不检查错误,但这是一个快速而肮脏的示例,仅用于演示使用基本身份验证的 SSL 保护的 Apache HttpClient 的功能。