第5章 客户端 API - 5.9. Securing a Client 保护 Client 安全

优质
小牛编辑
124浏览
2023-12-01

本节描述了 如何在 Jersey 客户端设置 SSL 配置(使用 JAX-RS API)。SSL 配置是设置在 ClientBuilder 。这个 client builder 包含了 KeyStore, TrustStore 或者整个 SslContext方法的定义。见下面示例:

  1. SSLContext ssl = ... your configured SSL context;
  2. Client client = ClientBuilder.newBuilder().sslContext(ssl).build();
  3. Response response = client.target("https://example.com/resource").request().get();

下面示例展示了如何设置一个自定义的 SslContext 到 ClientBuilder。创建 SslContext 有时很难,你可能需要初始化实例使用适当的协议,KeyStore,TrustStore,等。Jersey 提供了一个实用SslConfigurator 类,可用于安装 SSLContext。SslConfigurator 可以配置基于标准系统属性的SSL 配置,所以举例你可以配置文件使用环境 KeyStore 变量javax.net.ssl.keyStore 和 SslConfigurator 会使用这样的变量设置 SslContext。详见SslConfigurator。下面的代码显示了如何 SslConfigurator 被用来创建一个自定义 SSL 上下文。

  1. SslConfigurator sslConfig = SslConfigurator.newInstance()
  2. .trustStoreFile("./truststore_client")
  3. .trustStorePassword("secret-password-for-truststore")
  4. .keyStoreFile("./keystore_client")
  5. .keyPassword("secret-password-for-keystore");
  6. SSLContext sslContext = sslConfig.createSSLContext();
  7. Client client = ClientBuilder.newBuilder().sslContext(sslContext).build();

请注意,您还可以设置 KeyStore 和 TrustStore 在 ClientBuilder 实例,而无需包装成 SSLContext。然而,SslContext 将覆盖任何预先定义的 KeyStore 和 TrustStore 设置。ClientBuilder 还提供了一个自定义的 HostnameVerifier实现方法。当默认主机的 URL 验证失败,HostnameVerifier 的实现将调用时。

重要

请注意,使用 HTTP 和 SSL 有必要利用“https”方案。

目前默认的连接器提供者HttpUrlConnectorProvider 提供基于 HttpUrlConnection 的连接器,实现 JAX-RS 定义的 SSL的支持。

5.9.1. Http Authentication Support

Jersey 支持 Basic 和 Digest HTTP Authentication。

重要

在 Jersey 2.5 版本之前,org.glassfish.jersey.client.filter.HttpBasicAuthFilter 和 org.glassfish.jersey.client.filter.HttpDigestAuthFilter 提供支持。 Jersey 2.5 版后,这些过滤器是过时的(和在2.6版本就删除了),认证方法通过单一 Feature HttpAuthenticationFeature提供。

为了使客户端的 HTTP 认证支持在 Jersey 注册HttpAuthenticationFeature。这个功能可以提供的身份验证方法, digest 和 basic。Feature 可以工作在以下的模式:

  • BASIC:基本抢先认证。在抢占式模式,认证信息总是在每次 HTTP 请求时发送。这种模式比以下非抢占方式更常见的(如果你需要基本的认证你可能会使用这种先发制人的方式)。这种模式,必须结合 SSL/TLS使用,密码只发送 BASE64 编码。
  • BASIC NON-PREEMPTIVE:基本非抢占式模式。在该模式下认证信息只在服务器拒绝请求状态是 401,然后请求重复认证信息。这种模式对性能有负面影响。优点是它不会发送凭据时当不需要它们的时候。这种模式,必须结合 SSL/TLS使用,密码只发送 BASE64 编码。
  • DIGEST:HTTP 摘要认证。不需要 SSL/TLS 的用法。
  • UNIVERSAL: digest 和 basic 身份验证的组合。在非抢占式模式特征,这意味着它发送请求,不带认证信息。如果返回 401 状态码,请求重复,适当的认证是基于在响应请求的身份验证(定义 WWW-Authenticate HTTP 头文件。这个 feature 记得这身份验证请求是成功的给定 URI 和下一次尝试之前验证此 URI 与最新的成功的身份验证方法。

初始化次 feature ,使用静态方法 和 feature 的 builder。举例,Basic 认证:

  1. HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("user", "superSecretPassword");

基本非抢占式模式:

  1. HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder()
  2. .nonPreemptive().credentials("user", "superSecretPassword").build();

你也可以在没有任何默认凭据建立 feature:

  1. ttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().build();

在这种情况下,你需要在每个请求属性中提供用户名和密码:

  1. Response response = client.target("http://localhost:8080/rest/homer/contact").request()
  2. .property(HTTP_AUTHENTICATION_BASIC_USERNAME, "homer")
  3. .property(HTTP_AUTHENTICATION_BASIC_PASSWORD, "p1swd745").get();

这允许你重用相同的客户端认证给许多不同的凭据。

详见 HttpAuthenticationFeature