使用Spring RestTemplate访问Https Rest服务

zde*_*sam 42 rest https spring certificate resttemplate

任何人都可以使用Spring rest模板为我提供代码示例来访问使用https保护的休息服务URL.

我有证书,用户名和密码.基本身份验证在服务器端使用,我想创建一个客户端,可以使用提供的证书,用户名和密码(如果需要)连接到该服务器.

小智 27

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(new File(keyStoreFile)),
  keyStorePassword.toCharArray());

SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
  new SSLContextBuilder()
    .loadTrustMaterial(null, new TrustSelfSignedStrategy())
    .loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
    .build(),
    NoopHostnameVerifier.INSTANCE);

HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(
  socketFactory).build();

ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
  httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
MyRecord record = restTemplate.getForObject(uri, MyRecord.class);
LOG.debug(record.toString());
Run Code Online (Sandbox Code Playgroud)

  • 这是完全不安全的。没有服务器证书验证(“TrustSelfSignedStrategy”),没有主机名验证(“NoopH​​ostnameVerifier”)。提供的密钥材料用于客户端证书身份验证,但问题表明它使用 HTTP 基本身份验证。在这种情况下,从密钥库加载的内容根本不会被使用。 (3认同)

Avi*_*Avi 16

这里有一些代码可以为您提供一般的想法.

您需要创建自定义ClientHttpRequestFactory才能信任证书.它看起来像这样:

final ClientHttpRequestFactory clientHttpRequestFactory =
        new MyCustomClientHttpRequestFactory(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER, serverInfo);
    restTemplate.setRequestFactory(clientHttpRequestFactory);
Run Code Online (Sandbox Code Playgroud)

这是实施MyCustomClientHttpRequestFactory:

public class MyCustomClientHttpRequestFactory  extends SimpleClientHttpRequestFactory {

private final HostnameVerifier hostNameVerifier;
private final ServerInfo serverInfo;

public MyCustomClientHttpRequestFactory (final HostnameVerifier hostNameVerifier,
    final ServerInfo serverInfo) {
    this.hostNameVerifier = hostNameVerifier;
    this.serverInfo = serverInfo;
}

@Override
protected void prepareConnection(final HttpURLConnection connection, final String httpMethod)
    throws IOException {
    if (connection instanceof HttpsURLConnection) {
        ((HttpsURLConnection) connection).setHostnameVerifier(hostNameVerifier);
        ((HttpsURLConnection) connection).setSSLSocketFactory(initSSLContext()
            .getSocketFactory());
    }
    super.prepareConnection(connection, httpMethod);
}

private SSLContext initSSLContext() {
    try {
        System.setProperty("https.protocols", "TLSv1");

        // Set ssl trust manager. Verify against our server thumbprint
        final SSLContext ctx = SSLContext.getInstance("TLSv1");
        final SslThumbprintVerifier verifier = new SslThumbprintVerifier(serverInfo);
        final ThumbprintTrustManager thumbPrintTrustManager =
            new ThumbprintTrustManager(null, verifier);
        ctx.init(null, new TrustManager[] { thumbPrintTrustManager }, null);
        return ctx;
    } catch (final Exception ex) {
        LOGGER.error(
            "An exception was thrown while trying to initialize HTTP security manager.", ex);
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我的serverInfo对象包含服务器的指纹.您需要实现TrustManager接口以获取SslThumbprintVerifier要验证证书的任何其他方法(您也可以决定也始终返回true).

该值org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER允许所有主机名.如果需要验证主机名,则需要以不同方式实现它.

我不确定用户和密码以及如何实现它.通常,您需要 使用如下所示的值向restTemplatenamed 添加标头Authorization:Base: <encoded user+password>.在user+password必须Base64进行编码.


Max*_*meF 8

这是一个没有弃用类或方法的解决方案:( Java 8批准)

CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);

RestTemplate restTemplate = new RestTemplate(requestFactory);
Run Code Online (Sandbox Code Playgroud)

  • 任何时候您忽略证书都会带来安全风险。我假设(希望?)OP 计划使用它进行测试 (4认同)
  • 使用`NoopH​​ostnameVerifier`有安全风险。 (3认同)