1. HTTPS概念

1)简介

HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。这个系统的最初研发由网景公司进行,提供了身份验证与加密通讯方法,现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。

2)HTTPS和HTTP的区别

  a. https协议需要到ca申请证书,一般免费证书很少,需要交费。

  b. http是超文本传输协议,信息是明文传输;https 则是具有安全性的ssl加密传输协议。

  c. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

d. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

3)HTTPS的作用

它的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

  a. 一般意义上的https,就是服务器有一个证书。主要目的是保证服务器就是他声称的服务器,这个跟第一点一样;服务端和客户端之间的所有通讯,都是加密的。

  b. 具体讲,是客户端产生一个对称的密钥,通过服务器的证书来交换密钥,即一般意义上的握手过程。

  c. 接下来所有的信息往来就都是加密的。第三方即使截获,也没有任何意义,因为他没有密钥,当然篡改也就没有什么意义了。

  d.少许对客户端有要求的情况下,会要求客户端也必须有一个证书。

这里客户端证书,其实就类似表示个人信息的时候,除了用户名/密码,还有一个CA 认证过的身份。因为个人证书一般来说是别人无法模拟的,所有这样能够更深的确认自己的身份。目前少数个人银行的专业版是这种做法,具体证书可能是拿U盘(即U盾)作为一个备份的载体。

2.SSL简介

  1)简介

  SSL (Secure Socket Layer)为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取及窃听。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。

  2)SSL提供的服务

  a.认证用户和服务器,确保数据发送到正确的客户机和服务器

  b.加密数据以防止数据中途被窃取

  c.维护数据的完整性,确保数据在传输过程中不被改变。

  3) SSL协议的握手过程

  SSL 协议既用到了公钥加密技术又用到了对称加密技术,对称加密技术虽然比公钥加密技术的速度快,可是公钥加密技术提供了更好的身份认证技术。SSL 的握手协议非常有效的让客户和服务器之间完成相互之间的身份认证,其主要过程如下:

  ①客户端的浏览器向服务器传送客户端SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。

  ②服务器向客户端传送SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。

  ③客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;如果合法性验证通过,将继续进行第四步。

  ④用户端随机产生一个用于后面通讯的“对称密码”,然后用服务器的公钥(服务器的公钥从步骤②中的服务器的证书中获得)对其加密,然后传给服务器。

  ⑤服务器用私钥解密“对称密码”(此处的公钥和私钥是相互关联的,公钥加密的数据只能用私钥解密,私钥只在服务器端保留。详细请参看: http://zh.wikipedia.org/wiki/RSA算法),然后用其作为服务器和客户端的“通话密码”加解密通讯。同时在SSL 通讯过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。

  ⑥客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤⑤中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。

  ⑦服务器向客户端发出信息,指明后面的数据通讯将使用的步骤⑤中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。

  ⑧SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。

3.配置服务器端证书

  为了能实施SSL,一个web服务器对每个接受安全连接的外部接口(IP 地址)必须要有相应的证书(Certificate)。关于这个设计的理论是一个服务器必须提供某种合理的保证以证明这个服务器的主人就是你所认为的那个人。这个证书要陈述与这个网站相关联的公司,以及这个网站的所有者或系统管理员的一些基本联系信息。

  这个证书由所有人以密码方式签字,其他人非常难伪造。对于进行电子商务(e-commerce)的网站,或其他身份认证至关重要的任何商业交易,认证书要向大家所熟知的认证权威(Certificate Authority (CA))如VeriSign或Thawte来购买。这样的证书可用电子技术证明属实。实际上,认证权威单位会担保它发出的认证书的真实性,如果你信任发出认证书的认证权威单位的话,你就可以相信这个认证书是有效的。

  关于权威证书的申请,请参考:http://www.cnblogs.com/mikespook/archive/2004/12/22/80591.aspx

  在许多情况下,认证并不是真正使人担忧的事。系统管理员或许只想要保证被服务器传送和接收的数据是秘密的,不会被连接线上的偷窃者盗窃到。庆幸的是,Java提供相对简单的被称为keytool的命令行工具,可以简单地产生“自己签名”的证书。自己签名的证书只是用户产生的证书,没有正式在大家所熟知的认证权威那里注册过,因此不能确保它的真实性。但却能保证数据传输的安全性。

  用Tomcat来配置SSL主要有下面这么两大步骤:

  1)生成证书

  a. 在命令行下执行:

  %Java_home%\bin\keytool -genkey -alias tomcat -keyalg RSA

  在此命令中,keytool是JDK自带的产生证书的工具。把RSA运算法则作为主要安全运算法则,这保证了与其它服务器和组件的兼容性。

这个命令会在用户的home directory产生一个叫做" .keystore " 的新文件。在执行后,你首先被要求出示keystore密码。Tomcat使用的默认密码是" changeit "(全都是小写字母),如果你愿意,你可以指定你自己的密码。你还需要在server.xml配置文件里指定自己的密码,这在以后会有描述。

  b .你会被要求出示关于这个认证书的一般性信息,如公司,联系人名称,等等。这些信息会显示给那些试图访问你程序里安全网页的用户,以确保这里提供的信息与他们期望的相对应。

  c.你会被要求出示密钥(key)密码,也就是这个认证书所特有的密码(与其它的储存在同一个keystore文件里的认证书不同)。你必须在这里使用与keystore密码相同的密码。(目前,keytool会提示你按ENTER键会自动帮你做这些)。

  如果一切顺利,你现在就拥有了一个可以被你的服务器使用的有认证书的keystore文件。

  2) 配置tomcat

  第二个大步骤是把secure socket配置在$CATALINA_HOME/conf/server.xml文件里。$CATALINA_HOME代表安装Tomcat的目录。一个例子是SSL连接器的元素被包括在和Tomcat一起安装的缺省server.xml文件里。它看起来象是这样:

$CATALINA_HOME/conf/server.xml

----------- Define a SSL Coyote HTTP/1.1 Connector on port 8443 ------------

< Connector

port="8443" minProcessors="5" maxProcessors="75"

enableLookups="true" disableUploadTimeout="true"

acceptCount="100" debug="0" scheme="https" secure="true";

clientAuth="false" sslProtocol="TLS"/>

  Connector元素本身,其默认形式是被注释掉的(commented out),所以需要把它周围的注释标志删除掉。然后,可以根据需要客户化(自己设置)特定的属性。一般需要增加一下keystoreFile和keystorePass两个属性,指定你存放证书的路径(如:keystoreFile="C:/.keystore")和刚才设置的密码(如:keystorePass="123456")。关于其它各种选项的详细信息,可查阅Server Configuration Reference。

  在完成这些配置更改后,必须象重新启动Tomcat,然后你就可以通过SSL访问Tomcat支持的任何web应用程序。只不过指令需要像下面这样:https://localhost:8443

4.客户端代码实现

  在Java中要访问Https链接时,会用到一个关键类HttpsURLConnection;参见如下实现代码:

        // 创建URL对象        URL myURL = new URL("https://www.sun.com");

// 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象        HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();

// 取得该连接的输入流,以读取响应内容        InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream());

// 读取服务器的响应内容并显示        int respInt = insr.read();while (respInt != -1) {System.out.print((char) respInt);respInt = insr.read();}

  在取得connection的时候和正常浏览器访问一样,仍然会验证服务端的证书是否被信任(权威机构发行或者被权威机构签名);如果服务端证书不被信任,则默认的实现就会有问题,一般来说,用SunJSSE会抛如下异常信息:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building 
failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification 
path to requested target

上面提到SunJSSE,JSSE(Java Secure Socket Extension)是实现Internet安全通信的一系列包的集合。它是一个SSL和TLS的纯Java实现,可以透明地提供数据加密、服务器认证、信息完整性等功能,可以使我们像使用普通的套接字一样使用JSSE建立的安全套接字。JSSE是一个开放的标准,不只是Sun公司才能实现一个SunJSSE,事实上其他公司有自己实现的JSSE,然后通过JCA就可以在JVM中使用。

  关于JSSE的详细信息参考官网Reference:http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html;
  以及Java Security Guide:http://java.sun.com/j2se/1.5.0/docs/guide/security/;

  在深入了解JSSE之前,需要了解一个有关Java安全的概念:客户端的TrustStore文件。客户端的TrustStore文件中保存着被客户端所信任的服务器的证书信息。客户端在进行SSL连接时,JSSE将根据这个文件中的证书决定是否信任服务器端的证书。在SunJSSE中,有一个信任管理器类负责决定是否信任远端的证书,这个类有如下的处理规则:
1)若系统属性javax.net.sll.trustStore指定了TrustStore文件,那么信任管理器就去jre安装路径下的lib/security/目录中寻找并使用这个文件来检查证书。
2)若该系统属性没有指定TrustStore文件,它就会去jre安装路径下寻找默认的TrustStore文件,这个文件的相对路径为:lib/security/jssecacerts
3)若jssecacerts不存在,但是cacerts存在(它随J2SDK一起发行,含有数量有限的可信任的基本证书),那么这个默认的TrustStore文件就是lib/security/cacerts

  那遇到这种情况,怎么处理呢?有以下两种方案:
  1)按照以上信任管理器的规则,将服务端的公钥导入到jssecacerts,或者是在系统属性中设置要加载的trustStore文件的路径;证书导入可以用如下命令:keytool -import -file src_cer_file –keystore dest_cer_store;至于证书可以通过浏览器导出获得;
  2)、实现自己的证书信任管理器类,比如MyX509TrustManager,该类必须实现X509TrustManager接口中的三个method;然后在HttpsURLConnection中加载自定义的类,可以参见如下两个代码片段,其一为自定义证书信任管理器,其二为connect时的代码:

  

package test;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class MyX509TrustManager implements X509TrustManager {

X509TrustManager sunJSSEX509TrustManager;MyX509TrustManager() throws Exception {// create a "default" JSSE X509TrustManager.        KeyStore ks = KeyStore.getInstance("JKS");ks.load(new FileInputStream("trustedCerts"),"passphrase".toCharArray());TrustManagerFactory tmf =TrustManagerFactory.getInstance("SunX509", "SunJSSE");tmf.init(ks);TrustManager tms [] = tmf.getTrustManagers();

for (int i = 0; i < tms.length; i++) {if (tms[i] instanceof X509TrustManager) {sunJSSEX509TrustManager = (X509TrustManager) tms[i];return;}}

throw new Exception("Couldn't initialize");}

public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {try {sunJSSEX509TrustManager.checkClientTrusted(chain, authType);} catch (CertificateException excep) {// do any special handling here, or rethrow exception.        }}

public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {try {sunJSSEX509TrustManager.checkServerTrusted(chain, authType);} catch (CertificateException excep) {

}}

public X509Certificate[] getAcceptedIssuers() {return sunJSSEX509TrustManager.getAcceptedIssuers();}
}// 创建SSLContext对象,并使用我们指定的信任管理器初始化        TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new ;// 从上述SSLContext对象中得到SSLSocketFactory对象        SSLSocketFactory ssf = sslContext.getSocketFactory();// 创建URL对象        URL myURL = new URL("https://ebanks.gdb.com.cn/sperbank/perbankLogin.jsp");// 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象        HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();httpsConn.setSSLSocketFactory(ssf);// 取得该连接的输入流,以读取响应内容        InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream());// 读取服务器的响应内容并显示        int respInt = insr.read();while (respInt != -1) {System.out.print((char) respInt);respInt = insr.read();}

  对于以上两种实现方式,各有各的优点,第一种方式不会破坏JSSE的安全性,但是要手工导入证书,如果服务器很多,那每台服务器的JRE都必须做相同的操作;第二种方式灵活性更高,但是要小心实现,否则可能会留下安全隐患;

  参考文献:        

  http://baike.baidu.com/view/14121.htm

  http://zh.wikipedia.org/wiki/RSA算法

  http://blog.csdn.net/sfdev/article/details/2957240

  http://blog.csdn.net/cyberexp2008/article/details/6695691

==============================================================

SSL原理及Java实现

标签: ssljava加密解密tomcat服务器

Https 实际上是两种协议的组合

Https = Http + SSL

SSL原理

1 首先利用不对称算法握手,交换一个对称的密钥

2 然后利用这个对称的密钥进行通信

原理: 
要想保证网络通信的安全,我们第一反应就是给传输的数据加密,这也是现行安全传输通用的模式。但在传统加密方式(单密钥,对称加密)下,密钥不可避免的要 被传送于网络节点之间,(除非是写死到各个节点中,不过那样就没有任何灵活性和普适性),在一定强度的网络攻击下,这种加密方式是很脆弱的。 
SSL 的出现解决了这个难题,理解SSL 的关键是理解非对称加密的含义。 
在对称加密的情况下,源数据A,通过使用密钥B,加密成为密文C。任何人,只要获得了密钥B,就能够对截获的密文C解密,还原出源数据A。(依靠"算法安 全"远不如依靠"密钥安全");在非对称加密中,出现了“密钥对”的概念,即有一个公共密钥(公钥)和一个私有密钥(私钥),经公钥加密的密文只能由私钥 解密,反过来,经私钥加密的密文只能由公钥解密。这是个重要的特性(数学原理可参考RSA算法),下面的模拟https通信流程说明了这一特性的重要。 
1,客户端向服务端发出请求,服务端将公钥(以及服务端证书)响应给客户端;
2,客户端接收到服务器端端公钥与证书,验证证书是否在信任域内,不信任则结束通信,信任则使用服务端传过来的公钥生成一个“预备主密码”,返回给服务端。
3,服务端接收客户端传过来的“预备主密码”密文,使用私钥解密。非对称加密的安全性也就在于此了,第三方无法获取到“预备主密码”的明文,因为除了服务端,其他任何人是没有私钥的。
4,双方使用“预备主密码”生成用于会话的“主密码”。确认后,结束本次SSL 握手,停止使用非对称加密。
5,双方使用“主密码”对称加密传输数据,直到本次会话结束。
总结整个流程:先采用非对称加密模式,保证“主密码”只被通信双方获知,而后使用传统的对称加密方式通信,这样,保证了密钥安全(即“主密码”)就等于保 证了数据安全。之所以建立安全连接后,转而使用对称加密,是因为非对称加密的运算量很大,用于“常态”的数据通信十分低效。
以上描述的仅是SSL 协议中加密通信的原理,没有涉及到证书验证,以及客户端,服务端模式。

实现: JDK里面自带了一个密钥生成工具keytool,可以通过它生成SSL 通信需要的密钥对,或者生成自签名的证书。所有密钥对或者签名证书都是存放在“keystore”密钥仓库中,由它来管理。
下面结合具体例子说明:( 
1,生成服务端密钥仓库, 
keytool -genkey -alias svrkey -keyalg RSA -keystore d:/svr.jks -validity 365 
"alias"是生成的密钥别名,密钥的导入导出都需要由别名来定位。 
"keystore"生成的密钥仓库 
"validity"生成密钥仓库的有效期(天) 
随后会要求输入密钥仓库入口密码,比如: lostsky_11
输完密码后,接着会要求一系列的输入,无非是单位,所在地区之类的信息, 
但是第一项很重要!为输入服务端域名或IP,如: 192.168.1.3或www.591pic.com 
必须与服务器域名或IP相同,否则
SSL 连接无法建立(这也是SSL 通信验证的一部分) 
2,在tomcat_home/conf/server.xml中配置: 
找到ssl 通信配置那一段,加入: 
keystoreFile="d:/svr.jks" keystorePass="lostsky_11" 
服务器启动时会从中寻找用于建立ssl 连接的密钥 
3,导出服务端证书 
keytool -export -alias svrkey -file d:/svr.cer -keystore d:/svr.jks 
"alias"为想导出的密钥的别名,"file"为导出的证书,"keystore"为存储着导出密钥的仓库 
4,生成客户端密钥仓库 
keytool -genkey -alias clientkey -keyalg RSA -keystore d:/client.jks 
会要求输入仓库密码:如:midsky
5,将服务端证书导入到客户端密钥仓库 
keytool -import -file d:/svr.cer -keystore d:/client.jks 
会要求输入客户端密钥仓库的密码:如上是:midsky
这样服务端的密钥仓库就在tomcat部署完毕了, 
6,在客户端,每次访问服务端之前,加入 
"System.setProperty("javax.NET.ssl .trustStore","d://client.jks"); 
System.setProperty("javax.Net.ssl .trustStorePassword","midsky"); " 
就把服务端证书添加到了客户端的信任域中,能够完成ssl 通信。 
注:ssl 通信主要验证三个方面: 
a, 证书是否可信(第6步) 
b, 证书是否过期(第1步:validity) 
c, 证书地址是否和当前访问地址符合(第1步) 
客户端添加信任域还有编程的动态方法,但是那样会降低通信的安全性,对于证书相对固定的服务,不建议使用。 
以上是客户端对于服务端的验证,这也是SSL 默认的实现方式。在这种方式下,每次通信时,发起请求方(如PC中的BROWSER)都会验证响应方(如某个WEB服务端)的证书是否在己方信任域中,对 方的证书是否过期,对方的域名或IP,是否与信任域中证书记载的一致;不符合其中任何一项,通信都会被拒绝。但反过来,响应方是不对请求方做任何验证的。 所以有些需要双向验证的服务(比如某些服务只能对特定的拥有证书的用户开放),就需要添加客户端证书,由服务端来验证了,原理和实现与默认模式类似。

Java安全通信:HTTPS与SSL相关推荐

  1. java 发起HTTPS请求-SSL客户端

    一:采取文章:http://blog.sina.com.cn/s/blog_afe616ab0101eerj.html public static void main1()throws Excepti ...

  2. jodd忽略ssl证书_关于java访问https资源时,忽略证书信任问题

    java程序在访问https资源时,出现报错 sun.security.validator.ValidatorException: PKIX path building failed: sun.sec ...

  3. 使用Java访问https接口javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

    jdk1.6,证书:SHA256+TLSv1.2 使用Java访问https://**************** 接口     控制台提示握手失败错误:javax.net.ssl.SSLHandsh ...

  4. java实现https请求

    参考: https://www.cnblogs.com/chinway/p/5802541.html java 实现https请求 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易 ...

  5. HTTP、HTTPS、SSL总结

    HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议: 它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息,它使用安全套接字 ...

  6. https、SSL与数字证书介绍

    在互联网安全通信方式上,目前用的最多的就是https配合ssl和数字证书来保证传输和认证安全了.本文追本溯源围绕这个模式谈一谈. 名词解释 首先解释一下上面的几个名词: https:在http(超文本 ...

  7. java实现https免证书认证

    java实现https免证书认证 解决方法: 1.下载两个包,httpclient-4.2.jar和httpcore-4.2.jar,复制以下代码就可使用. 2.调用类代码: String httpO ...

  8. 给自己的网址加上https,添加ssl证书(springboot项目)

    给自己的网址加上https,添加ssl证书 1.先去阿里云官网首页,登录,找到 *SSL证书* 2.点击 *立即购买* 3.选择好点击确定就可以 4.输入自己的域名和手机号,等待即可,成功他就叫给你发 ...

  9. JAVA免费https,Java与HTTPS

    什么是HTTPS 严格地讲,HTTPS并不是一个单独的协议,而是对工作在一加密连接(TLS或SSL)上的常规HTTP协议的称呼. TLS/SSL 关于TLS/SSL的介绍网上已经有很多,大家可以参考& ...

最新文章

  1. 三菱服务器显示d01,MR-J3-D01基础知识三菱MR-J3-D01指导手册(通用接口) - 广州正凌...
  2. Java 向上类型转换与向下类型转换的理解【复习】
  3. homeassistant树莓派cpu_集成ESP8266的WiFi RGB灯泡接入Home Assistant
  4. Yii学习笔记之二(使用gii生成一个简单的样例)
  5. 紧急整理了 20 道 Spring Boot 面试题,我经常拿来面试别人
  6. 前端学习(1426):ajax封装
  7. 腾讯、网易回应被约谈:严格落实未成年人防沉迷规定
  8. Windows开机 桌面一片空白 无法操作
  9. Struts2学习笔记(十八) 防止表单重复提交
  10. alter table add column多个字段_element中el-table单行暂无数据和整体暂无数据的默认修改...
  11. 网站流量日志分析系统笔记(Hadoop大数据技术原理与应用)
  12. 特殊的空格-ASCII码值160
  13. FastFDS--文件服务系统
  14. qpython3h手机版怎么发短信_阿里云短信 python3代码发送短信
  15. POJ 3088 Push Botton Lock 笔记
  16. java-获取电池电量
  17. Android Studio Error:前言中不允许有内容
  18. 解决硬盘分区错误, 纯Dos磁盘工具Diskpart的用法.
  19. d3dcompiler_43.dll的错误怎么解决?
  20. reflection removal

热门文章

  1. cvpr2020 人脸检测与识别_CVPR 2020 | 旷视研究院提出数据不确定性算法 DUL,优化人脸识别性能...
  2. miui 9.0的android版本下载,MIUI9.0+Android7.1体验版
  3. pytorch 使用GPU计算f1_score
  4. 生活是残酷的,但依然要去热爱它
  5. 【Unity】Unity Gizmos扩展(圆弧、扇形、圆形)
  6. Overleaf中参考文献引用失败
  7. 压电式压力传感器工作原理
  8. html文字段落 带标题,HTML标题跟段落
  9. 史上最全讲解:JAVA中的方法 数组 类
  10. 挖掘城市ip_【案例】抖音话题 50 亿,解码城市 IP「抖 in city」的爆款法则