无法在Jersey中进行基本的http身份validation

我正在尝试使用Jersey 1.X版本连接到安全的外部rest服务。

我使用了以下代码

public class MyRestClient { private static final String API_USER_NAME = "some value"; private static final String API_PASSWORD = "some value"; private static final String REST_URL = "https://"; public static void main(String[] args) { ClientConfig config = new DefaultClientConfig(); Client client = Client.create(config); client.addFilter(new HTTPBasicAuthFilter(API_USER_NAME, API_PASSWORD)); WebResource webResource = client.resource(UriBuilder.fromUri(REST_URL).build()); ClientResponse response = webResource.post(ClientResponse.class); System.out.println(response); } } 

但我一直在打这个例外..

 com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching 'somevalue' found 

我检查了这个外部rest服务的API,它说它支持基本的HTTP身份validation,但我不知道为什么我一直在遇到这个错误。

有什么想法吗?

由于Basic Auth本身缺乏安全性,它通常通过SSL完成,您可以在URL中的https架构中看到。 使用SSL,使用证书 。 SSL握手包括服务器发送其证书和客户端检查其信任库以查看证书是否可信。 该平台应具有其信任的证书颁发机构列表。 例如,如果我们尝试访问

 WebTarget target = client.target("https://wikipedia.org"); 

这将起作用,因为维基百科发送的证书由系统中的受信任机构签名。 另一方面,如果来自服务器的证书未由其中一个被篡改的权限签名,则SSL握手将失败。

如果是这种情况,则需要将Client配置为处理SSL握手,这就是您获得exception的原因。 您可以在此处看到有关如何配置Client以使用https一些好答案


UPDATE

你提供的链接已经死了,所以我不知道’myTrustManager’和’hostnameVerifier’是什么……你能分享一些关于如何提供这些信息的信息吗?

 import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; import com.sun.jersey.client.urlconnection.HTTPSProperties; import java.io.FileInputStream; import java.security.KeyStore; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import org.junit.Test; public class JUnitTest { private static final String TRUSTSTORE_FILE = " 

基本上,您需要从拥有API的人那里获得X.509证书 (请参阅下面的链接以获得编程方式)。 然后将其导入您的信任库。 这是您的客户端知道如何信任连接的方式。 如果您相信服务器是他们所说的人,则可以加密连接。

获得证书后,您可以使用Java keytool导入它。 通过做这个

keytool -import -alias serverCert -file -keystore

系统会要求您输入密码。 然后问你是否相信证书。 输入“是”,然后就完成了。 这是您输入的文件( client_trust_file )和密码,应该在上面的代码中使用。

  • 以编程方式将远程证书添加到您的信任库
  • 查看有关Java安全套接字框架的更多信息

更新2

有关使用Tomcat创建通过安全SSL连接的简单应用程序的说明。 使用上面的客户端代码来访问它。 我将使用Netbeans 8,但也会尝试以一般方式包含执行此操作的说明。 我也将使用Tomcat 8(配置可能与Tomcat 7有点不同。您应该查阅文档以了解任何差异)。 我将使用Maven,所以希望你习惯使用它。

步骤1:

创建一个新的应用程序。 我将从Maven原型创建一个简单的Jersey应用程序。 在Netbeans

文件→新建项目→Maven→项目原型→搜索“jersey-quickstart-webapp”; 选择groupId“org.glassfish.jersey.archetypes”→下一步→将项目命名为“secured-rest-app”→希望你能完成其余的工作。 您最终应该使用Maven应用程序。

在任何支持Maven的IDE中,只需查找带坐标的原型:

  • groupId:org.glassfish.jersey.archetypes
  • artifactId:jersey-quickstart-webapp
  • 版本:2.13

从命令行:执行

 mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-grizzly2 \ -DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false \ -DgroupId=com.example -DartifactId=secured-rest-app -Dpackage=secured.rest.app \ -DarchetypeVersion=2.13 

第2步:

我们需要在应用程序中设置基本身份validation。 这可以在web.xm l中完成。 打开项目的web.xml并将其添加到

   Secured Rest App /webapi/*   *    BASIC secured-rest-app.com   user  

第3步:

现在我们只需要在Tomcat中设置领域。 默认情况下,Tomcat使用领域名称UserDatabaseRealm 。 它基本上只是从xml文件中读取。 这可能不是生产中最理想的方式,但这是一个最简单的例子。 有关领域的更多信息,请参阅领域配置HOW-TO 。 对于此特定领域,已经设置了该文件。 我们只需要添加我们的用户。 打开/conf/tomcat-users.xml并在输入以下用户

  

步骤4:

现在我们可以测试一下。 如果您已经在Netbeans上安装了Tomcat,我们需要做的就是Run并选择服务器。 这应该会自动打开我们的index.jsp浏览器。 该文件不受保护,因为它不符合out安全约束的/webapi/* 。 单击Jersey资源链接,您将看到Basic Auth登录。 输入peeskillet并分别输入用户名和密码的密码。 现在您可以访问该资源。

第5步:

以上所有内容只是为我们设置基本身份validation,但由于所有Basic Auth都只是对我们的用户名和密码进行base64编码,因此可以轻松解码,因此我们需要通过安全连接进行身份validation。

我们需要做的第一件事是为我们的服务器创建一个密钥库。 我们将要做的是创建一个自签名证书,该证书只能在开发中完成。 在生产中,您将需要从受信任的CA颁发机构获取证书

cd/conf并输入以下内容(全部在一行)

 keytool -genkey -alias localhost -keyalg RSA -keysize 1024 -dname "CN=localhost" -keypass supersecret -keystore tomcat-keystore.jks -storepass supersecret 

您现在应该在conf目录中看到一个文件tomcat-keystore.jks 。 现在我们可以导出证书了。

 keytool -export -alias localhost -rfc -keystore ./tomcat-keystore.jks > ./tomcat.cert 

系统将提示您输入密码,输入supersecret 。 您现在应该看到在conf目录中创建的tomcat.cert文件。 将该文件复制到您在上面创建的应用程序的项目根目录中。

从命令行cd到项目根目录, tomcat.cert的位置并键入以下内容

 keytool -import -alias tomcatCert -file ./tomcat.cert -keystore ./client-truststore.jks 

系统将提示您输入信任库的密码。 使用trustpass 。 您需要输入两次。 完成后,它将提示信任证书,输入yes并输入。 您现在应该在项目根目录中看到client-truststore.jks文件。 这是我们将用于客户端应用程序的内容。

现在我们只需要配置Tomcat以使用我们的密钥库进行连接。 在/conf/server.xml ,在元素内。 (注意Tomcat 7可能会略有不同)

  

最后,在我们的webapp中,我们应该通过改变来添加安全连接支持

   Secured Rest App /webapi/*   *   CONFIDENTIAL   

现在我们设置使用我们的客户端代码。

第6步:

上面的代码使用Jersey 1客户端。 我们正在使用Jersey 2,因此代码会略有不同。 在应用程序的任何位置,只需使用main方法创建一个类来运行我们的客户端。 这是我使用的:

 import java.io.FileInputStream; import java.security.KeyStore; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.core.Response; import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; public class SimpleClientApp { private static final String TRUSTSTORE_FILE = "client-truststore.jks"; private static final String TRUSTSTORE_PASSWORD = "trustpass"; private static final String APP_URL = "https://localhost:8443/secured-rest-app/webapi/myresource"; public static void main(String[] args) throws Exception { KeyStore truststore = KeyStore.getInstance("JKS"); truststore.load(new FileInputStream(TRUSTSTORE_FILE), TRUSTSTORE_PASSWORD.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(truststore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); Client client = ClientBuilder.newBuilder() .sslContext(sslContext).build(); client.register(HttpAuthenticationFeature.basic("peeskillet", "secret")); Response response = client.target(APP_URL).request().get(); System.out.println(response.readEntity(String.class)); } } 

你应该能够运行它,它应该打印出来Got it! 。 我们完成了!

由于这个特定的问题是关于泽西1,我只是提到你可以轻松创建一个泽西1应用程序。 从第一步开始,只需使用Maven原型的坐标即可

  • groupId:com.sun.jersey.archetypes
  • artifactId:jersey-quickstart-webapp
  • 版本:1.18.1

在Netbeans中,只需按照上述步骤操作,但选择jersey-quickstart-webappcom.sun.jersey.archetypes版本。

使用Jersey 1,您可以使用原始答案中的代码,只需添加Basic Authfilter,就像OP在原始post中所做的那样,设置用户名和密码并更改URL当然。

如果post中有任何错误,请告诉我。 我还没有机会certificate这一点:-)

一些资源

  • Tomcat 8 SSL / TLS配置如何
  • Tomcat 8领域配置如何
  • Tomcat 7领域配置如何
  • Tomcat 7 SSL / TLS配置如何