无法在泽西岛进行基本的 http 身份验证身份验证、泽西、基本、http

由网友(糯米团子)分享简介:我正在尝试使用 Jersey 1.X 版本连接到安全的外部休息服务.I am trying to connect to a secure external rest service using Jersey 1.X version.我使用了以下代码public class MyRestClient{privat...

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

I am trying to connect to a secure external rest service using Jersey 1.X version.

我使用了以下代码

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);
  }
}

但我一直遇到这个异常..

But I keep hitting this exception..

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

我查看了这个外部 rest 服务的 API,它说它支持基本 HTTP 身份验证,但我不知道为什么我总是遇到这个错误.

I checked out the API of this external rest service and it says it support Basic HTTP authentication but I dont know why I keep hitting this error.

有什么想法吗?

推荐答案

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

Because the lack of security in Basic Auth by itself, it's usually done over SSL, as you can see in the https schema in the URL. With SSL, there are certificates used. The SSL handshake consists of the server sending its certificate and the client checking its truststore to see if the certificate is trusted. The platform should have a list of Certificate authorities that it trusts. For instance if we try and access

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

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

this will work as the cert sent by wikipedia is signed by a trusted authority in the system. On the other hand, if the certificate from the server is not signed by one of those trused authorities, then the SSL handshake will fail.

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

If this is the case, then Client needs to be configured to handle the SSL handshake, that's why you are getting the exception. You can see some good answers here on how to configure the Client for working with https

您提供的链接已失效,所以我不知道 'myTrustManager' 和 'hostnameVerifier' 是什么...您能分享一些有关如何提供的信息吗?

The link you have provided is dead so I dont know what 'myTrustManager' and 'hostnameVerifier' is...can you share some info on how can I supply that?

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));
    } 
}

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

Basically you need to get the X.509 Certificate from the people who own the API (see link below for programmatic way). Then you import it into your trust store. This is how your client knows to trust the connection. If you trust that the server is who they say they are, then the connection can be encrypted.

获得证书后,您可以使用 Java 密钥工具.通过这样做

Once you have the cert you can import it with the Java keytool. By doing this

keytool -import -alias serverCert -file -keystore <client_trust_file>

您将被要求输入密码.然后问你是否信任证书.输入是",然后你就完成了.这是您输入的文件 (client_trust_file) 和密码,应该在上面的代码中使用.

You will be asked for a password. Then asked if you trust the cert. Type 'yes', then you're done. This is the file (client_trust_file) and password you typed, should be used in the above code.

以编程方式将远程证书添加到您的信任库详细了解 Java 安全套接字框架

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

Instructions on creating a simple app that is over a secured SSL connection with Tomcat. The use the client code above to access it. I am going to be using Netbeans 8, but will try to include instructions for doing this in a general way also. I will also be using Tomcat 8 (the configuration may be a bit different fro Tomcat 7. You should consult the documentation for any differences). I will be using Maven, so hopefully you are comfortable using it.

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

Crate a new app. I will create a simple Jersey app from a Maven archetype. In Netbeans

文件 →新项目→马文→来自 Archetype 的项目 →搜索jersey-quickstart-webapp";选择 groupId "org.glassfish.jersey.archetypes" →下一个→将项目命名为secured-rest-app" →希望你能完成剩下的.你应该最终得到一个 Maven 应用程序.

File → New Project → Maven → Project from Archetype → Search "jersey-quickstart-webapp"; choose the one with groupId "org.glassfish.jersey.archetypes" → Next → Name the project "secured-rest-app" → Hopefully you can complete the rest. You should end up with a Maven app.

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

In any other IDE that supports Maven, just look for an archetype with the coordinates:

groupId:org.glassfish.jersey.archetypesartifactId: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 步:

技术分享 多种测试HTTP身份验证的方法

我们需要在应用程序中设置基本身份验证.这可以在 web.xml 中完成.打开项目的 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 文件中读取.这可能不是生产中最理想的方式,但这是最容易使用的示例.有关领域的更多信息,请参阅 领域配置方法.对于这个特定领域,文件已经设置好了.我们只需要添加我们的用户.打开/conf/tomcat-users.xml,在