HTTPS和TLS

现在很多数据的传输都开始采用https协议,而且,据说谷歌将在其浏览器强制推行https协议,苹果也有强制推行https,ios上应用的http协议已经成为了过去,http被https取代已经是大势所趋。本质上,https协议可以说是http协议+TLS,那么,TLS是什么,为什么要放弃原本的http,而需要在http上加一层壳,采用https呢?

http协议,可以说是网络传输过程中最重要的协议之一,但是其传输过程存在很大的安全隐患。可能存在数据泄露,被篡改等问题。大家在访问一些应用或网站的时候,经常会发现屏幕的某个地方存在一些“不正常的”广告,很多应用会因为这个问题用户投诉,笔者的朋友曾在有派进行移动端的开发,曾因为app服务器被dns劫持,而在应用的很多地方被插入广告,遭到大量投诉,事实上,被dns劫持的事情时有发生,劫持后常常会在html文档中插入一些js脚本,特别是常常被运营商劫持。

其实TLS的早期版本有另外一个名字,SSL。但是SSL的早期版本存在很多问题,所以用户一直很少,这个情况一直到上个世纪九十年代后期,SSL的版本较为完善,用户一下多了起来,于是,SSL被改名为TLS,这可能是想让用户忘记早期SSL的槽糕印象吧。

理解了取代http的必要性和TLS和SSL和关系,下面就来了解一下https,主要是https的流程。

首先是单向验证,即客户端会对服务器进行身份验证。

1.客户端访问服务器端前,会将本地的加密算法列表,http版本列表以及生成的一个随机字符串发送到服务器端,常伟16位或32位。加密算法列表,即支持的加密算法类型,数据加密一般使用对称加密的方式,常见的算法有AES-128,AES-256,DES等。

2.服务器端接收到客户端的消息后,会根据自己的加密算法列表,匹配“最优”的算法,并匹配http版本,同时,生成一个随机字符串,将这些信息加上自己的签名公钥发送到客户端。

3.现在客户端和服务器端都有两个随机字符串。客户端拿到server的签名公钥后,先去CA进行验证,若验证通过,确定了server的身份没有被冒充。客户端就会和server端一样,利用两个随机字符串,经过复杂的算法,生成对称加密的密钥,这个过程采用的算法有效保证server和client生成的密钥是相同。


关于双向认证,其实和单项认证类似。一般在金融行业应用比较多,服务器需要对client进行身份认证。双向认证代价比较大,若是向CA购买一套密钥认证是需要一定的金额,若是给一个超过千万用户的应用每个客户生成一套密钥,代价将会非常昂贵。所以,有些公司采用只使用一套密钥,如有派。当然,也有自定义签名证书,如12306。




以下是使用Java代码实现采用HTTPSTLS 1.2版本建立连接,并完成双向TLS认证(mTLS)的示例: ```java import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; public class SSLExample { public static void main(String[] args) throws Exception { // Load client certificate and private key for mTLS String keyStorePath = "client.jks"; String keyStorePassword = "password"; String keyPassword = "password"; KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(SSLExample.class.getClassLoader().getResourceAsStream(keyStorePath), keyStorePassword.toCharArray()); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, keyPassword.toCharArray()); // Load server truststore for server certificate verification String trustStorePath = "server.jks"; String trustStorePassword = "password"; KeyStore trustStore = KeyStore.getInstance("JKS"); trustStore.load(SSLExample.class.getClassLoader().getResourceAsStream(trustStorePath), trustStorePassword.toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); // Create SSL context with TLS 1.2 protocol and mTLS configuration SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); // Set default SSL context for HTTPS connection HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); // Create URL object for HTTPS endpoint URL url = new URL("https://example.com/api"); // Open HTTPS connection HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); // Set request method and headers connection.setRequestMethod("GET"); connection.setRequestProperty("User-Agent", "Mozilla/5.0"); // Get response from HTTPS endpoint try (InputStream inputStream = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (SSLException e) { e.printStackTrace(); } finally { connection.disconnect(); } } // Trust manager to accept all server certificates private static final TrustManager[] TRUST_ALL_CERTIFICATES = new TrustManager[] { new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Do nothing } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Do nothing } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }; } ``` 在上面的示例中,我们使用了Java的`HttpsURLConnection`类来建立连接。我们首先加载客户端证书和私钥,并使用它们来创建`KeyManager`对象。然后,我们加载服务器信任库并使用它来创建`TrustManager`对象。接下来,我们使用这些`KeyManager`和`TrustManager`对象创建一个SSL上下文对象,该对象使用TLS 1.2协议并完成mTLS配置。最后,我们将默认的SSL上下文设置为HTTPS连接,并打开连接以向服务器发送请求。 在此示例中,我们还提供了一个`TrustManager`实现,它接受所有服务器证书。这不是一个好的做法,因为它会使您的应用程序容易受到中间人攻击。在实际生产环境中,您应该使用一个更安全的`TrustManager`实现,它会验证服务器证书并拒绝不受信任的证书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值