springboot实现https双向传输协议的示例代码
作者:WellAdjested
本文主要介绍了springboot实现https双向传输协议的示例代码,包含配置证书和私钥路径、调用请求方法等步骤,具有一定的参考价值,感兴趣的可以了解一下
1.https 双向传输协议概念
1.1. 单向认证
- 我们在通常访问一个网站,例如百度。这是一个单向的TLS认证。
- 具体的过程为:
- 服务器发送证书给客户端。
- 客户端验证证书有效之后,客户端和服务器协商出一个对称加密密钥。
- 由服务端的私钥加密,并发送给客户端。
- 客户端收到之后再用公钥解密这个对称密钥。然后就开始用对称密钥加密传输的数据。
- 特征:
- 服务端并不校验客户端的合法性,来者不拒,绝大部分的网站都是这种类型。
- 只有客户端校验服务器端的合法性。
1.2. 双向认证
- 有时候我们在一些安全性要求较高的场景下,服务器也需要来校验客户端的合法性。
- 具体的过程为:
- 在客户端验证了服务器证书的合法性之后,客户端需要带上自己的证书发送给服务器。
- 服务器收到证书之后,比对服务器在信任链中是否信任了客户端的证书。
- 如果信任,则服务端校验客户端合法。
- 如果证书不在服务端的受信列表上,则拒绝服务。
- 这样子其实就是建立了一条双向认证的TLS传输通道。即互相校验证书。
1.3. 非对称加密交互流程
- 如果用到的是非对称加密,那么你和第三方之间就有两对公私钥,各自持有对方的公钥和自己的私钥。网络通讯中我们一般用自己的私钥将报文加签,用第三方提供的公钥将报文中涉及安全隐私的部分加密,然后第三方会用我们提供公钥进行验签,验签通过后再用他们自己的私钥将报文加密部分解密;
1.4. csr文件
- CSR 即证书签名申请(Certificate Signing Request),获取 SSL 证书,需要先生成 CSR 文件并提交给证书颁发机构(CA)。CSR 包含了用于签发证书的公钥、用于辨识的名称信息(Distinguished Name)(例如域名)、真实性和完整性保护(例如数字签名),通常从 Web 服务器生成 CSR;
- 证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书。
1.5. 生成证书相关流程
# 1. 生成客户端csr和私钥key 执行这个指令后会生成csr文件和私钥key openssl req -new -nodes -sha256 -newkey rsa:2048 -keyout privateKey.key -out request.csr # 生成csr文件后,将csr文件发送给甲方,甲方签发了ca.pem给我们 # 后续访问甲方接口,就一直携带ca.pem和本地私钥 用于传输过程中的文件和数据加密;
2. 使用springboot实现https双向传输协议实例
2.1. 配置证书和私钥路径
- 在配置文件中配置证书和私钥路径,使得项目能够访问到;
- ca.pem,privateKey.key
2.2. 调用请求方法
// 调用方法 resp = apiService.request(true, POST, url, req);
2.3. ApiService层方法
@Override public String request(Boolean ssl, HttpMethod method, String url, String reqBody) throws Exception { // 调用下方的request方法 return request(ssl, method, url, null, reqBody); } // 双向认证请求 @Override public String request(Boolean ssl, HttpMethod method, String url, MultiValueMap<String, String> params, String reqBody) throws Exception { logger.info("request url to server =====> {}", url); logger.info("request body to server =====> {}", reqBody); // 根据实际需求添加请求头 HttpHeaders headers = new HttpHeaders(); headers.set("token", ""); ResponseEntity<String> resp = sslService.request(ssl, url, method, headers, params, reqBody); String respBody = resp.getBody(); logger.info("resp body from server =====> {}", respBody); return respBody; }
2.4. sslService类中方法
@Override public ResponseEntity<String> request(Boolean ssl, String url, HttpMethod method, HttpHeaders headers, MultiValueMap<String, String> params, String reqBody) throws Exception { HttpsClient client = !ssl ? new HttpsClient(ssl) : new HttpsClient(ssl, "证书路径", "私钥路径"); return RestClientUtil.request(client, url, method, headers, params, reqBody); }
2.5. HTTPS通信双向认证工具类
/** * @Description //HTTPS通信双向认证工具类 **/ @Data public class HttpsClient { // true-启用双向认证,false-不启用 private boolean ssl; // 服务端公钥 private String serverPem; // 客户端私钥 private String clientSK; public HttpsClient() { } public HttpsClient(Boolean ssl) { this.ssl = ssl; } public HttpsClient(Boolean ssl, String serverPem, String clientSK) { this.ssl = ssl; this.serverPem = serverPem; this.clientSK = clientSK; } }
2.6. RestClientUtil类中方法
public static ResponseEntity<String> request(HttpsClient client, String url, HttpMethod method, HttpHeaders httpHeaders, MultiValueMap<String, String> params, String reqBody) throws Exception { httpHeaders.set("Content-Type", "application/json; charset=utf-8"); HttpEntity<?> requestEntity = new HttpEntity<>(reqBody, httpHeaders); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).queryParams(params); // UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParams(params); RestTemplate rest = client.isSsl() ? new RestTemplate(HttpsClientUtil.rsaHttpComponentsClientHttpRequestFactory(client)) : new RestTemplate(generateHttpRequestFactory()); return rest.exchange(builder.toUriString(), method, requestEntity, String.class); } /** * 忽略SSL证书 * * @return */ private static HttpComponentsClientHttpRequestFactory generateHttpRequestFactory() { TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true; SSLContext sslContext = null; try { sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier()); HttpClientBuilder httpClientBuilder = HttpClients.custom(); httpClientBuilder.setSSLSocketFactory(connectionSocketFactory); CloseableHttpClient httpClient = httpClientBuilder.build(); HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); factory.setHttpClient(httpClient); return factory; }
2.7. HttpsClientUtil类中方法
public static HttpComponentsClientHttpRequestFactory rsaHttpComponentsClientHttpRequestFactory(HttpsClient client) throws Exception { // 获取httpClient对象,防止重复创建--读取证书信息,对象生成后不做其他操作所以未加锁 if (httpClient == null) { httpClient = createCloseableHttpClientByRsa(client); } HttpComponentsClientHttpRequestFactory httpsFactory = new HttpComponentsClientHttpRequestFactory(httpClient); // httpsFactory.setReadTimeout(5000); // httpsFactory.setConnectTimeout(5000); httpsFactory.setReadTimeout(60 * 1000); httpsFactory.setConnectTimeout(60 * 1000); return httpsFactory; }
到此这篇关于springboot实现https双向传输协议的示例代码的文章就介绍到这了,更多相关springboot https双向传输内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!