概述
一、基本概念
HTTP(超文本传输协议):
以明文方式发送内容,不提供任何方式的数据加密。
HTTPS(超文本传输安全协议):
HTTPS = HTTP + 加密 + 身份验证 + 数据完整性。
二、区别之处:
http和https使用的是完全不同的连接方式,用的端口也不同,前者是80,后者是443;
http协议以明文方式发送内容,不提供任何方式的数据加密,https则是具有安全性的ssl加密传输协议。并且https协议需要到ca申请证书。
三、https工作流程:
1.tcp三次握手
2.客户端验证服务器数字证书
3.DH算法协商对称加密算法的秘钥、hash算法的秘钥
4.SSL安全加密隧道协商完成
5.网页以加密的方式传输,用协商的对称加密算法和秘钥加密,保证数据机密性;用协商的hash算法进项数据完整性保护,保证数据不被篡改。
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
四、https的加密方案:
对称加密 + 非对称加密 混合使用。
1、对称加密,密钥只有一个,用x加密,用x解密。比如你将要发的数据和密钥x异或一下得到的数据就是加密的,发送过去,再将加密数据与x异或进行解密。
2、非对称加密,有一对密钥,公钥+私钥。用公钥加密就用私钥解密,用私钥加密就用公钥解密。
通过hash散列把数据内容变成固定长度唯一的字符序列->称为数据摘要or数据指纹,再通过加密算法->形成数字签名,通信时将文本内容和数字签名一起发送。怎么检验是否数据被篡改,就拿文本内容同样hash算法成数据指纹,将数字签名解密成数据指纹,进行对比。
而在https中,密钥协商阶段采用非对称加密,数据通信阶段采用对称加密。客户端有一个对称加密的密钥下、服务端有非对称的一对密钥,客户端向服务端发送请求说我们商量一下密钥的事,服务端将公钥给客户端,客户端拿着公钥对自己的对称密钥x加密后发给服务端,因为只有服务端有非对称的私钥可以解密,然后服务端用私钥解密拿到客户端对称密钥,之后的数据通信都用对称密钥就可以了。
总结就是:用非对称加密的方式来传输对称加密过程中的密钥,采取对称加密的方式来传输数据。
如果有中间抓包本质问题是:client无法判断发来的密钥协商报文是否从合法服务器发来的。CA机构。
服务器拿着自己的公司信息,域名和公钥向CA机构申请证书,CA机构将服务器的所有信息进行hash散列后用私钥进行加密形成数字签名,此时证书就可以颁发给合法的服务器了。你中间人是可以用CA公钥解密,去修改服务器的私钥,但是你再hash后无法用CA私钥加密了。如果你中间人也去申请证书,但是你证书的域名不是服务器的域名,人家客户端就不会相信你的。
那么,如果需要在你的服务器里调用https的第三方接口,但服务器并没配置openssl证书,这时接口会直接返回错误:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target...
处理方式有两种:1.在配置https安全证书;2.代码中创建httpClient使用忽略验证方式。
第二中方式具体代码对比如下:
正常调用http接口:
private static <T> T baseRequest(String url, String token, Class<T> tClass) {
try {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(10000);// 设置超时
requestFactory.setReadTimeout(10000);
RestTemplate restTemplate = new RestTemplate(requestFactory);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Authorization", "Bearer " + token);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<T> httpEntity = new HttpEntity<>(null, httpHeaders);
ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, tClass);
if (200 == responseEntity.getStatusCode().value()) {
return responseEntity.getBody();
} else {
log.error("错误信息:rn" + responseEntity + "rn");
}
} catch (Exception e) {
log.error("错误信息:rn" + e.getMessage() + "rn");
}
return null;
}
改用http忽略验证方式:
private static <T> T baseRequest(String url, String token, Class<T> tClass) {
try {
IgnoreSSLRequestFactory requestFactory = new IgnoreSSLRequestFactory(httpClient());
requestFactory.setConnectTimeout(60000); //连接上服务器(握手成功)的时间
requestFactory.setReadTimeout(60000);
RestTemplate restTemplate = new RestTemplate(requestFactory);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Authorization", "Bearer " + token);
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<T> httpEntity = new HttpEntity<>(null, httpHeaders);
ResponseEntity<T> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, tClass);
if (200 == responseEntity.getStatusCode().value()) {
return responseEntity.getBody();
} else {
log.error("错误信息:rn" + responseEntity + "rn");
}
} catch (Exception e) {
log.error("错误信息:rn" + e.getMessage() + "rn");
}
return null;
}
private static HttpClient httpClient() throws KeyManagementException, NoSuchAlgorithmException {
SSLContextBuilder contextBuilder = new SSLContextBuilder();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(contextBuilder.build(), NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", new PlainConnectionSocketFactory())
.register("https", socketFactory).build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
connectionManager.setMaxTotal(200);
connectionManager.setDefaultMaxPerRoute(100);
CloseableHttpClient httpClient = HttpClientBuilder.create().setConnectionManager(connectionManager).build();
return httpClient;
}
import org.apache.http.client.HttpClient;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* 绕过证书
*/
public class IgnoreSSLRequestFactory extends SimpleClientHttpRequestFactory {
public IgnoreSSLRequestFactory(HttpClient httpClient) {
super();
}
@Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod)
throws IOException {
if (connection instanceof HttpsURLConnection) {
prepareHttpsConnection((HttpsURLConnection) connection);
}
connection.setConnectTimeout(3000);
connection.setReadTimeout(3000);
super.prepareConnection(connection, httpMethod);
}
private void prepareHttpsConnection(HttpsURLConnection connection) {
connection.setHostnameVerifier(new SkipHostnameVerifier());
try {
connection.setSSLSocketFactory(createSslSocketFactory());
} catch (Exception ex) {
// Ignore
}
}
private SSLSocketFactory createSslSocketFactory() throws Exception {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{new SkipX509TrustManager()},
new SecureRandom());
return context.getSocketFactory();
}
private class SkipHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}
private static class SkipX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}
读完的同学,你学废了吗?
知识点扩展:
RSA非对称加密算法;
DSA数字签名算法;
ECDSA椭圆曲线签名算法;
有兴趣的同学可以深入学习。
最后
以上就是老实砖头为你收集整理的深入理解-HTTP与HTTPS不同之处的全部内容,希望文章能够帮你解决深入理解-HTTP与HTTPS不同之处所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复