我正在尝试使用Jersey 1.X版本连接到安全的外部休息服务。
我用下面的代码
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://<somevalue>";
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身份验证,但我不知道为什么我一直遇到此错误。
有什么想法吗?
由于基本身份验证本身缺乏安全性,因此通常通过SSL来完成,如您https
在URL
的架构中所见。使用SSL时,会使用证书。SSL握手由服务器发送其证书和客户端检查其信任库组成,以查看证书是否受信任。该平台应具有其信任的证书颁发机构列表。例如,如果我们尝试访问
WebTarget target = client.target("https://wikipedia.org");
这将起作用,因为Wikipedia发送的证书是由系统中受信任的机构签名的。另一方面,如果来自服务器的证书未由这些受信任的授权机构之一签名,则SSL握手将失败。
如果是这种情况,则Client
需要进行配置以处理SSL握手,这就是为什么您会收到异常的原因。你可以看到一些很好的答案在这里上如何配置Client
与工作https
您提供的链接已死,所以我不知道“ 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 = "<location-of-truststore";
private static final String TRUSTSTORE_PASSWORD = "trustStorePassword";
@Test
public void test() 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("SSL");
sslContext.init(null, tmf.getTrustManagers(), null);
ClientConfig config = new DefaultClientConfig();
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
new HTTPSProperties(null, sslContext));
Client client = Client.create(config);
final String httpsUrl = "https://...";
ClientResponse response = client.resource(httpsUrl).get(ClientResponse.class);
System.out.println(response.getStatus());
System.out.println(response.getEntity(String.class));
}
}
基本上,您需要从拥有API的人员那里获得X.509证书(有关编程方式,请参见下面的链接)。然后,将其导入到信任库中。这就是您的客户端知道信任连接的方式。如果您相信服务器是他们所说的身份,则可以对连接进行加密。
获得证书后,可以使用Java
keytool
导入它。通过做这个
keytool -import -alias serverCert -file <cert.file> -keystore <client_trust_file>
系统将要求您输入密码。然后询问您是否信任证书。输入“是”,就可以完成。这是client_trust_file
您键入的文件()和密码,应在上面的代码中使用。
有关创建通过与Tomcat进行安全SSL连接的简单应用的说明。使用上面的客户端代码来访问它。我将使用Netbeans
8,但也将尝试以一般方式包括执行此操作的说明。我还将使用Tomcat 8(Tomcat
7的配置可能有所不同。有关任何差异,请查阅文档)。我将使用Maven,因此希望您习惯使用它。
创建一个新应用。我将从Maven原型创建一个简单的Jersey应用程序。在Netbeans中
文件→新项目→Maven→原型项目→搜索“ jersey-quickstart-webapp”;选择一个具有groupId“
org.glassfish.jersey.archetypes”的项目→下一步→将项目命名为“ secured-rest-
app”→希望您可以完成其余工作。您应该最终得到一个Maven应用程序。
在任何其他支持Maven的IDE中,只需查找具有以下坐标的原型:
从命令行:执行
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
我们需要在应用程序中设置基本身份验证。这可以在web.xm l中完成。打开项目的web.xml,并将其添加到</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured Rest App</web-resource-name>
<url-pattern>/webapi/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>secured-rest-app.com</realm-name>
</login-config>
<security-role>
<role-name>user</role-name>
</security-role>
现在我们只需要在Tomcat中设置领域。缺省情况下,Tomcat使用领域名称UserDatabaseRealm
。它基本上只是从xml文件读取。这可能不是生产中最理想的方式,但这是最简单的示例。有关领域的更多信息,请参见领域配置方法。对于此特定领域,该文件已设置。我们只需要添加我们的用户。打开<tomcat-home>/conf/tomcat- users.xml
并在其中输入以下用户<tomcat-users>
<user password="secret" roles="user" username="peeskillet"/>
现在我们可以对其进行测试。如果您已经在Netbeans上安装了Tomcat,那么我们要做的就是Run
选择服务器。这应该会自动打开浏览器index.jsp
。该文件不受保护,因为它不符合<url- pattern>/webapi/*</url- pattern>
out安全限制。单击泽西资源链接,您将看到基本身份验证登录。键入peeskillet
并secret
分别对用户名和密码。现在您可以访问资源。
以上所有内容都为我们设置了基本身份验证,但是由于所有基本身份验证只是对用户名和密码进行base64编码,因此可以轻松解码,因此我们需要通过安全连接进行身份验证。
我们需要做的第一件事是为我们的服务器创建一个密钥库。我们将要在这里创建一个自签名证书,该证书只能在开发中完成。在生产中,您将需要从受信任的CA权威机构获得证书。
cd
到<tomcat-home>/conf
并键入以下(全部在一行)
keytool -genkey -alias localhost -keyalg RSA -keysize 1024
-dname "CN=localhost"
-keypass supersecret
-keystore tomcat-keystore.jks
-storepass supersecret
您现在应该tomcat-keystore.jks
在conf
目录中看到一个文件。现在我们可以导出证书了。
keytool -export -alias localhost -rfc -keystore ./tomcat-keystore.jks > ./tomcat.cert
将提示您输入密码,键入supersecret
。现在,您应该tomcat.cert
在conf
目录中看到一个文件。将该文件复制到上面创建的应用程序的项目根目录中。
从命令行cd
到项目根目录,tomcat.cert
然后键入以下内容
keytool -import -alias tomcatCert -file ./tomcat.cert -keystore ./client-truststore.jks
系统将提示您输入信任库的密码。使用trustpass
。您将需要输入两次。完成后,它将提示您信任证书,键入yes
并输入。现在,您应该client- truststore.jks
在项目根目录中看到一个文件。这就是我们将用于客户端应用程序的内容。
现在,我们只需要配置Tomcat以使用我们的密钥库进行连接。在元素的<tomcat- home>/conf/server.xml
内部<Service>
。(请注意,Tomcat 7可能有所不同)
<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true"
scheme="https"
secure="true"
keystoreFile="absolute/path/to/tomcat-keystore.jks"
keystorePass="supersecret"
clientAuth="false"
sslProtocol="TLS" />
最后,在我们的网络应用中,我们应该通过更改以下内容来添加安全连接支持: <security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured Rest App</web-resource-name>
<url-pattern>/webapi/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
现在我们准备使用我们的客户代码。
上面的代码使用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!
。大功告成!
由于这个特定问题是关于Jersey 1的,因此我只想提一下您可以轻松创建Jersey 1应用程序。从第一步开始,只需使用Maven原型的坐标
在Netbeans中,只需按照上述步骤操作,但是选择的com.sun.jersey.archetypes
版本jersey-quickstart- webapp
。
使用Jersey 1,您可以使用原始答案中的代码,只需添加Basic Auth过滤器即可,就像OP在原始帖子中所做的那样,设置用户名和密码并更改url。
如果帖子中有任何错误,请告诉我。 我还没有机会对此进行校对:-)
一些资源
问题内容: 我已经使用JAX-RS,Jersey和Grizzly编写了一个简单的REST服务器。这是我启动服务器的方式: 现在,我需要使用基本HTTP身份验证来保护资源,而且我不知道该怎么做。 如果可以更轻松地使它工作,我可以从Grizzly切换到Jetty,但是我确实很看重Grizzly提供的简单配置/启动。 我读了很多教程。他们都提到了web.xml,但是在我当前的配置中我没有一个。(我需要为
问题内容: 我试图模仿Java中此curl命令的功能: 我使用Commons HttpClient 3.0编写了以下内容,但最终还是从服务器上获取了一个。有人可以告诉我我做错了什么吗? 我后来尝试了Commons HttpClient 4.0.1,但仍然遇到相同的错误: 问题答案: 好的,这样可以工作。万一有人想要它,这是对我有用的版本:)
问题内容: 我想写书,所使用的一个一个的NodeJS REST的API服务器Joyent的,并且一切正常,除了我无法验证普通用户的身份验证。如果我跳到终端并执行,则无法在NodeJS http服务器上获取值username:password。如果我的NodeJS http服务器类似于 ,是否应该在来自回调的 req 对象中某处获取值username:password ?如何获得这些值而不必使用Co
我尝试了angular.js,并从一个restful api的web-ui开始(使用超文本传输协议基本授权)。这真的很好,除了授权工作。 到目前为止,我使用的是设置密码,但大多数情况下浏览器会打开http basic auth的默认登录表单。另一个奇怪的行为是angular请求不包含授权头(选项和GET请求都不包含)。我还尝试使用header配置在每个请求上设置此header,但这也不起作用。 有
我一直试图用restTemplate传递基本身份验证,但它甚至没有将身份验证头传递给服务器。下面是我使用的bean定义` `
问题内容: 我目前正在尝试使用HTTP和HTTPS访问URL。我尝试访问的URL需要基本身份验证。使用HTTP可以正常工作,但是使用HTTPS则不能。我不确定是否需要使用HTTPS添加其他内容。该URL应该返回给我的文本是键值格式,可以加载到对象中。 这是到目前为止我尝试过的代码。 这是证书类别 当我删除所有证书代码(以及证书代码)时的错误消息: 问题答案: 问题似乎是由于在更改连接的和实例之前打