搞懂https

最近应公司安全组的要求,所有系统对外请求方式由http方式改为https方式,因为https请求方式对数据进行了加密,http请求方式没有,显然https请求方式是安全的。但是https如何保证数据在网络传输的时候是安全的呢?项目中如何配置改造呢?我们需要了解一下加密算法和数字证书的概念。

1.对称加密

服务器端生成密钥,然后把密钥发送给客户端,服务端给客户端发送数据时,使用密钥将数据加密传给客户端,客户端收到数据后使用密钥进行解密。如下图:


微信截图_20181029154717.png

同理:客户端使用参数向服务端请求数据时,先用密钥将参数加密,然后传给服务器,服务器收到数据后用密钥将数据解密。
缺点:密钥在网络传输的过程中容易被第三者获取,第三者就可以使用密钥对数据进行加密解密,导致了数据泄露或者服务器被攻击。
常见的对称加密算法有:DES加密算法

2.非对称加密

对称加密出现的问题是密钥在传输过程中容易被黑客获取。为了解决密钥安全传输的问题,我们使用非对称加密算法。在非对称加密中,服务端和客户端都有两把钥匙,一个是公钥(对所有人公开),一个是私钥(只有自己知道),使用公钥加密的数据只能使用对应的私钥进行解密,使用私钥加密的数据只能使用对应的公钥进行解密。这样,在数据传输的过程中,服务端使用客户端的公钥对数据进行加密,客户端收到数据后,使用私钥进行解密。同理,客户端想服务端请求数据也一样。如下图:


微信截图_20181029162107.png

缺点:非对称加密效率比较低,比对称加密慢了上百倍。
优化:
我们可以使用对称加密和非对称加密结合的方式来优化,我们可以使用非对称加密的方式传输对称加密过程中需要的密钥,之后就可以使用对称加密的方式传输数据了,例如:服务器使用明文发送公钥给客户端,客户端收到公钥后先生成密钥(对称加密使用),然后使用收到的公钥对密钥加密传输给服务端,服务端使用该密钥解密,最终服务器端安全得到密钥,服务器端和客户端就可以使用对称加密进行加密了。
缺点:服务端在给客户端发送公钥的时候,黑客截取公钥,把自己的公钥冒充为服务器的公钥发给客户端。客户端收到公钥以后,无法确定是否是服务器发来的,这时候客户端就会用黑客的公钥进行加密生成密钥。然后在客户端把密钥传输给服务器的时候,黑客又拦截了密钥,最终成了客户端和黑客在通信。更有甚者,黑客再对这把密钥用刚才服务器的公钥进行加密,再发给服务器,这样服务器和客户端的通信完全暴露给了黑客。

常见的非对称加密算法有:RSA、椭圆曲线加密算法

3.数字证书

非对称加密之所以不安全是因为,客户端不知道接收到的公钥是否是服务器的,因此我们需要证明客户端收到的公钥就是服务器的,即证明我是我。为了解决这个问题就需要引入数字证书:
我们需要一个证书认证机构CA(Certificate Authority),CA提供私钥,颁发证书。
数字证书的具体加密解密流程见下图(这个图是我从网上找的):


微信截图_20181030102400.png

1.服务器将公钥和服务器信息使用hash算法生成摘要
2.为防止摘要被黑客窃取,服务器使用CA提供的私钥对摘要进行加密生成数字签名。
3.服务器将数字签名和公钥、服务器信息合并在一起生成数字证书。
4.客户端拿到数字证书,使用CA提供的公钥对数字证书里的数字签名进行解密得到数字摘要,并对数字证书里的公钥和服务器信息使用hash算法得到另一份数字摘要。
5.将两份摘要进行对比,如果一样,则证明消息是服务端发过来的。
这样就保证了数据传输的安全。

4.SSL协议和TSL协议

HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,使用https协议必须从CA申请一个用于证明服务器用途类型的书。

SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。该协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层:SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS记录协议和TLS握手协议。

5.java发送https请求


import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * Created by  on 2018/10/30.
 */
public class HttpsUtils {

    private static CloseableHttpClient httpClient;
    private static CloseableHttpResponse httpResponse;

    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext context = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy(){
                // 信任所有
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }

            }).build();

            SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE);

            return HttpClients.custom().setSSLSocketFactory(factory).build();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }


    public static String sendhttpsMsg(Map params, String url) {
        try {
            HttpPost httpPost = new HttpPost(url);
            List list = new ArrayList<>();

            if (params != null) {
                for (String key : params.keySet()) {
                    list.add(new BasicNameValuePair(key, params.get(key).toString()));
                }
            }
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");

            httpPost.setEntity(entity);
            httpClient = HttpsUtils.createSSLClientDefault();
            httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            if (httpEntity != null) {
                String jsonStr = EntityUtils.toString(httpEntity, "UTF-8");
                return jsonStr;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                httpResponse.close();
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Map map = new HashMap<>();
        map.put("sl_id_nbank_num_ai", "0");
        System.out.println(HttpsUtils.sendhttpsMsg(map, "https://localhost:9090/xxx/xxx"));

    }
}

你可能感兴趣的:(搞懂https)