问题
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
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
回答1:
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.
Mat Mannion (@MatMannion) described probably a more common method, which should work with the current version: 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)
@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.
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
<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());
}
}
realm.properties
admin: admin123, admin
root: passw0rd, user
Client.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.
来源:https://stackoverflow.com/questions/19679320/basic-authentication-using-http-commons-client