起初我看过这篇文章 How can you authenticate using the Jersey Client against a JAAS enabled web-server?
但它只适用于Jersey 1.x版本。我的问题是如何在Jersey 2.x中实现相同的行为?
我需要能够从我的servlet调用安全的休息服务,并且我使用Jersey 2.11客户端api。
我正在使用org.glassfish.jersey.core版本2.11
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.11</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.11</version>
<exclusions>
<exclusion>
<artifactId>javax.ws.rs-api</artifactId>
<groupId>javax.ws.rs</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json</artifactId>
<version>2.0-m05</version>
<exclusions>
<exclusion>
<artifactId>jettison</artifactId>
<groupId>org.codehaus.jettison</groupId>
</exclusion>
<exclusion>
<artifactId>jaxb-impl</artifactId>
<groupId>com.sun.xml.bind</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.11</version>
</dependency>
WEB.XML
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
在我的servlet中,我创建了我的客户端(自定义):
JerseyClient client = new JerseyClient(baseURL+getallclinics);
Response clientresponse = client.get_JSON();
logger.debug("Client Response: " + clientresponse);
这是JerseyClient类:
/**
*
*/
package toto;
import javax.net.ssl.*;
import java.io.*;
import java.net.Socket;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.*;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
public class JerseyClient {
private WebTarget webTarget;
private Client client;
private ClientConfig clientConfig;
//private static final String BASE_URI = "https://localhost:8443/testsecurity2/resources";
private static final String truststore_path = "/var/toto/toti/security/truststore.jks";
private static final String truststore_password = "changeit";
private static final String keystore_path = "/var/toto/toti/security/keystore.jks";
private static final String keystore_password = "changeit";
private static final String url = "https://localhost/restapi/";
public JerseyClient() {
ClientConfig config = new ClientConfig(); // SSL configuration
// SSL configuration
// new Jersey 2.x way to do it
client = ClientBuilder.newBuilder()
.sslContext(getSSLContext())
.hostnameVerifier(getHostnameVerifier())
.build();
webTarget = client.target(url);
}
public JerseyClient(String URL) {
// SSL configuration
client = ClientBuilder.newBuilder()
.sslContext(getSSLContext())
.hostnameVerifier(getHostnameVerifier())
.build();
webTarget = client.target(URL);
}
public <T> T get_XML(Class<T> responseType) {
return webTarget.request(MediaType.APPLICATION_JSON).get(responseType);
}
public <T> T get_JSON(Class<T> responseType) {
return webTarget.request(MediaType.APPLICATION_JSON).get(responseType);
}
public Response get_JSON() {
return webTarget.request(MediaType.APPLICATION_JSON).get();
}
public void close() {
client.close();
}
public void setUsernamePassword(String username, String password) {
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic(username, password);
client.register(feature);
}
private HostnameVerifier getHostnameVerifier() {
return new HostnameVerifier() {
@Override
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
return true;
}
};
}
private SSLContext getSSLContext() {
TrustManager mytm[] = null;
KeyManager mykm[] = null;
try {
mytm = new TrustManager[]{new MyX509TrustManager(truststore_path, truststore_password.toCharArray())};
mykm = new KeyManager[]{new MyX509KeyManager(keystore_path, keystore_password.toCharArray())};
} catch (Exception ex) {
ex.printStackTrace();
}
SSLContext ctx = null;
try {
ctx = SSLContext.getInstance("SSL");
ctx.init(mykm, mytm, null);
} catch (java.security.GeneralSecurityException ex) {
}
return ctx;
}
/**
* Taken from http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html
*
*/
static class MyX509TrustManager implements X509TrustManager {
/*
* The default PKIX X509TrustManager9. We'll delegate
* decisions to it, and fall back to the logic in this class if the
* default X509TrustManager doesn't trust it.
*/
X509TrustManager pkixTrustManager;
MyX509TrustManager(String trustStore, char[] password) throws Exception {
this(new File(trustStore), password);
}
MyX509TrustManager(File trustStore, char[] password) throws Exception {
// create a "default" JSSE X509TrustManager.
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(trustStore), password);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(ks);
TrustManager tms[] = tmf.getTrustManagers();
/*
* Iterate over the returned trustmanagers, look
* for an instance of X509TrustManager. If found,
* use that as our "default" trust manager.
*/
for (int i = 0; i < tms.length; i++) {
if (tms[i] instanceof X509TrustManager) {
pkixTrustManager = (X509TrustManager) tms[i];
return;
}
}
/*
* Find some other way to initialize, or else we have to fail the
* constructor.
*/
throw new Exception("Couldn't initialize");
}
/*
* Delegate to the default trust manager.
*/
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
try {
pkixTrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException excep) {
/*
* Possibly pop up a dialog box asking whether to trust the
* cert chain.
*/
}
}
/*
* Merely pass this through.
*/
public X509Certificate[] getAcceptedIssuers() {
return pkixTrustManager.getAcceptedIssuers();
}
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
// TODO Auto-generated method stub
}
} // end class MyX509TrustManager
/**
* Inspired from http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html
*
*/
static class MyX509KeyManager implements X509KeyManager {
/*
* The default PKIX X509KeyManager. We'll delegate
* decisions to it, and fall back to the logic in this class if the
* default X509KeyManager doesn't trust it.
*/
X509KeyManager pkixKeyManager;
MyX509KeyManager(String keyStore, char[] password) throws Exception {
this(new File(keyStore), password);
}
MyX509KeyManager(File keyStore, char[] password) throws Exception {
// create a "default" JSSE X509KeyManager.
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keyStore), password);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509", "SunJSSE");
kmf.init(ks, password);
KeyManager kms[] = kmf.getKeyManagers();
/*
* Iterate over the returned keymanagers, look
* for an instance of X509KeyManager. If found,
* use that as our "default" key manager.
*/
for (int i = 0; i < kms.length; i++) {
if (kms[i] instanceof X509KeyManager) {
pkixKeyManager = (X509KeyManager) kms[i];
return;
}
}
/*
* Find some other way to initialize, or else we have to fail the
* constructor.
*/
throw new Exception("Couldn't initialize");
}
public PrivateKey getPrivateKey(String arg0) {
return pkixKeyManager.getPrivateKey(arg0);
}
public X509Certificate[] getCertificateChain(String arg0) {
return pkixKeyManager.getCertificateChain(arg0);
}
public String[] getClientAliases(String arg0, Principal[] arg1) {
return pkixKeyManager.getClientAliases(arg0, arg1);
}
public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
return pkixKeyManager.chooseClientAlias(arg0, arg1, arg2);
}
public String[] getServerAliases(String arg0, Principal[] arg1) {
return pkixKeyManager.getServerAliases(arg0, arg1);
}
public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) {
return pkixKeyManager.chooseServerAlias(arg0, arg1, arg2);
}
} // end class MyX509KeyManager
} // end class JerseyClient
答案 0 :(得分:1)
Jersey 2 ClientRequestFilter可能会解决基于表单的身份验证问题。
听到的是相同的代码段。
class FormAuthenticateFilter实现ClientRequestFilter {
private ArrayList<Object> cookies = new ArrayList<>();
public FormAuthenticateFilter(Client client, List<String> params) {
WebTarget baseTarget = client.target("http://localhost:8080");
Form form = new Form();
form.param("__ac_name", "username");
form.param("__ac_password", "password");
form.param("submitted", "true");
Response response = baseTarget.path("/cookieAuthHelper/login_form")
.request("application/x-www-form-urlencoded")
.post(Entity.form(form));
Map<String, NewCookie> cr = response.getCookies();
for (NewCookie cookie : cr.values()) {
cookies.add(cookie.toCookie());
}
}
public void filter(ClientRequestContext requestContext) throws IOException {
if (cookies != null) {
requestContext.getHeaders().put("Cookie", cookies);
}
}
并最终将过滤器注册到您的球衣2客户端。
Client client = ClientBuilder.newClient();
client.register(new FormAuthenticateFilter());
谢谢, Brinal