What is the right way to send a client certificate with every request made by the resttemplate in spring?

佐手、 提交于 2019-11-27 16:40:09

问题


i want to consume a REST service with my spring application. To access that service i have a client certificate (self signed and in .jks format) for authorization. What is the proper way to authenticate against the rest service?

This is my request:

public List<Info> getInfo() throws RestClientException, URISyntaxException {

    HttpEntity<?> httpEntity = new HttpEntity<>(null, new HttpHeaders());

    ResponseEntity<Info[]> resp = restOperations.exchange(
            new URI(BASE_URL + "/Info"), HttpMethod.GET, 
            httpEntity, Info[].class);
    return Arrays.asList(resp.getBody());
}

回答1:


Here is example how to do this using RestTemplate and Apache HttpClient

You should define your own RestTemplate with configured SSL context:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
    char[] password = "password".toCharArray();

    SSLContext sslContext = SSLContextBuilder.create()
            .loadKeyMaterial(keyStore("classpath:cert.jks", password), password)
            .loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();

    HttpClient client = HttpClients.custom().setSSLContext(sslContext).build();
    return builder
            .requestFactory(new HttpComponentsClientHttpRequestFactory(client))
            .build();
}

 private KeyStore keyStore(String file, char[] password) throws Exception {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    File key = ResourceUtils.getFile(file);
    try (InputStream in = new FileInputStream(key)) {
        keyStore.load(in, password);
    }
    return keyStore;
}

Now all remote calls performed by this template will be signed with cert.jks. Note: You would need to put cert.jks into your classpath

@Autowired
private RestTemplate restTemplate;

public List<Info> getInfo() throws RestClientException, URISyntaxException {
    HttpEntity<?> httpEntity = new HttpEntity<>(null, new HttpHeaders());

    ResponseEntity<Info[]> resp = restTemplate.exchange(
            new URI(BASE_URL + "/Info"), HttpMethod.GET, 
            httpEntity, Info[].class);
    return Arrays.asList(resp.getBody());
}



回答2:


Or you can just import the certificate to your JDKs cacerts, and all the HTTP clients using the jdk (rest template in your case) will use the certificate to make the REST call.

keytool -import -keystore $JAVA_HOME/jre/lib/security/cacerts -file foo.cer -alias alias

P.S: Don't forget to restart your server after successful import. Default password for keystore - changeit



来源:https://stackoverflow.com/questions/45713593/what-is-the-right-way-to-send-a-client-certificate-with-every-request-made-by-th

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!