优客服基于Nginx+tomcat的SSL改造

目录

 

1.为什么要做https和wss升级

2.https的相关名称解释

3.证书格式

4.oepnssl使用  安装OpenSSL

生成证书

解决subjectAlternativeName 找不到的问题

客户端

服务器端

5.xca使用

xca简介

xca安装步骤

xca使用

Step1. 打开XCA

Step2. 如果是第一次打开,请点击 File-->New Database

Step3. 选择证书数据存储的位置并命名存储文件的名字。

Step4. 设置密码保护证书数据

Step5: 鼠标点击到“Certificate Signing Request” 分页,并点击右边的“New Request”,将弹出下面的窗体。

Step6. 生成保护证书的秘钥:因为我们是生成证书请求,那么我们需要生成一个证书对,即私钥和公钥,上面Step6生成的信息是在公钥中可以看到的。

6.单向认证和双向认证

7.免费证书申请

8.单tomcat下配置https和wss

方案1

方案2

9.nginx+tomcat下配置半链路https和wss

部署说明

nginx 配置

10.nginx+tomcat下配置全链路https和wss

11.uat 环境如何使用免费证书

12.代码优化项

 

13.参考资料


1.为什么要做https和wss升级


直接原因:chrome62版本以后不支持http网站通知,但是网站通知又是一个非常重要的功能,用在新用户接入提醒,消息提醒,差评提醒,系统提醒等。

根本原因:Chrome和Firefox明确标记在没有HTTPS的情况下网站是不安全的,增加https后,提升了安全性。

  • HTTP 三大风险

   窃听风险(eavesdropping):第三方可以获知通信内容。

   篡改风险(tampering):第三方可以修改通信内容。

   冒充风险(pretending):第三方可以冒充他人身份参与通信。

  • HTTPS 解决方案

   所有信息都是加密传播,第三方无法窃听。

   具有校验机制,一旦被篡改,通信双方会立刻发现。

   配备身份证书,防止身份被冒充。

2.https的相关名称解释

 

  •    http协议:HTTP 是一种超文本传输协议,它是无状态的、简单快速的、基于 TCP 的可靠传输协议。HTTP 是明文传输的。
  •    https协议:HTTP over SSL,允许客户端和服务器首先建立加密的通信通道,然后通过它传递明文HTTP消息,有效地防止它们被窃听。
  •    http和https对比

   

  •    https示例

   

  •    TLS:传输层安全协议 Transport Layer Security的缩写
  •    SSL:安全套接字层 Secure Socket Layer的缩写。SSL是Netscape开发的专门用户保护Web通讯的,目前版本为3.0。最新版本的TLS 1.0是IETF(工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。两者差别极小,可以理解为SSL 3.1,它是写入了RFC的。

TLS与SSL对于不是专业搞安全的开发人员来讲,可以认为是差不多的,这二者是并列关系,详细差异见 http://kb.cnblogs.com/page/197396/

  •    KEY 通常指私钥。
  •    CSR 是Certificate Signing Request的缩写,即证书签名请求,这不是证书,可以简单理解成公钥,生成证书时要把这个提交给权威的证书颁发机构。
  •    CRT 即 certificate的缩写,即证书。
  •    X.509 是一种证书格式.对X.509证书来说,认证者总是CA或由CA指定的人,一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息。X.509的证书文件,一般以.crt结尾,根据该文件的内容编码格式,可以分为以下二种格式:
   PEM - Privacy Enhanced Mail,打开看文本格式,以"-----BEGIN..."开头, "-----END..."结尾,内容是BASE64编码.
   Apache和*NIX服务器偏向于使用这种编码格式.
   DER - Distinguished Encoding Rules,打开看是二进制格式,不可读.
   Java和Windows服务器偏向于使用这种编码格式
  •    OpenSSL 相当于SSL的一个实现,如果把SSL规范看成OO中的接口,那么OpenSSL则认为是接口的实现。接口规范本身是安全没问题的,但是具体实现可能会有不完善的地方,比如之前的"心脏出血"漏洞,就是OpenSSL中的一个bug.

3.证书格式

一般来说,主流的Web服务软件,通常都基于两种基础密码库:OpenSSL和Java。

Tomcat、Weblogic、JBoss等,使用Java提供的密码库。通过Java的Keytool工具,生成Java Keystore(JKS)格式的证书文件。

Apache、Nginx等,使用OpenSSL提供的密码库,生成PEM、KEY、CRT等格式的证书文件。

此外,IBM的产品,如Websphere、IBM Http Server(IHS)等,使用IBM产品自带的iKeyman工具,生成KDB格式的证书文件。微软Windows Server中的Internet Information Services(IIS),使用Windows自带的证书库生成PFX格式的证书文件。

如果您在工作中遇到带有后缀扩展名的证书文件,可以简单用如下方法区分:

*.DER *.CER : 这样的证书文件是二进制格式,只含有证书信息,不包含私钥。

*.CRT : 这样的文件可以是二进制格式,也可以是文本格式,一般均为文本格式,功能与*.DER/*.CER相同。

*.PEM : 一般是文本格式,可以放证书或私钥,或者两者都包含。 *.PEM如果只包含私钥,那一般用 *.KEY代替。

*.PFX *.P12 是二进制格式,同时含证书和私钥,一般有密码保护。

怎么判断是文本格式还是二进制?

用记事本打开,如果是规则的数字字母,如
—–BEGIN CERTIFICATE—–
MIIE5zCCA8+gAwIBAgIQN+whYc2BgzAogau0dc3PtzANBgkqh......
—–END CERTIFICATE—–
就是文本的,上面的BEGIN CERTIFICATE,说明这是一个证书
如果是—–BEGIN RSA PRIVATE KEY—–,说明这是一个私钥

这些证书格式之间是可以互相转换的

以下提供了一些证书之间的转换方法:

  •  将JKS转换成PFX

可以使用Keytool工具,将JKS格式转换为PFX格式。

keytool -importkeystore -srckeystore D:\server.jks -destkeystore D:\server.pfx -srcstoretype JKS -deststoretype PKCS12
  • 将PFX转换为JKS

可以使用Keytool工具,将PFX格式转换为JKS格式。

keytool -importkeystore -srckeystore D:\server.pfx -destkeystore D:\server.jks -srcstoretype PKCS12 -deststoretype JKS
  • 将PEM/KEY/CRT转换为PFX

使用OpenSSL工具,可以将密钥文件KEY和公钥文件CRT转化为PFX文件。

将密钥文件KEY和公钥文件CRT放到OpenSSL目录下,打开OpenSSL执行以下命令:

openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt
  • 将PFX转换为PEM/KEY/CRT

使用OpenSSL工具,可以将PFX文件转化为密钥文件KEY和公钥文件CRT。

将PFX文件放到OpenSSL目录下,打开OpenSSL执行以下命令:

openssl pkcs12 -in server.pfx -nodes -out server.pem

openssl rsa -in server.pem -out server.key

请注意:此步骤是专用于使用keytool生成私钥和CSR申请证书,并且获取到pem格式证书公钥的情况下做分离私钥使用的,所以在实际部署证书时请使用此步骤分离出来的私钥和申请下来的公钥证书做匹配使用。

云盾证书服务统一使用 PEM 格式的数字证书文件。


4.oepnssl使用  
安装OpenSSL

本来准备直接放一个链接在这的,但是感觉不是特别的准确,所以借鉴这个在写详细一些。
(1)OpenSSL下载( [https://www.openssl.org/source/(https://www.openssl.org/source/))没有提供windows版本的安装包,可以选择其他开源平台提供的工具。例如 http://slproweb.com/products/Win32OpenSSL.html
根据你的系统来选择不同的版本下载安装
 
点击运行文件后直接下一步就可以了,没有什么特殊设置。
(2)设置环境变量,例如工具安装在C:\OpenSSL-Win64,则将C:\OpenSSL-Win64\bin;复制到Path中

这个路径需要写自己的安装路径呀,exe在bin文件中,所以记得加上bin
部分借鉴:https://blog.csdn.net/kitok/article/details/72957185


生成证书


在bin(bin文件在安装目录里面)文件中打开cmd,依次输入以下命令:

注意:这里有一个大坑,我也是爬了好久的,所以先跟大家说明一下,再详细说命令。
由于Chrome 58 及以上版本只会使用 subjectAlternativeName 扩展程序(而不是 commonName)来匹配域名和网站证书。如果直接按照下面的步骤生成的ssl证书是不能直接在谷歌正常使用的,会说证书无效,并报错:NET::ERR_CERT_COMMON_NAME_INVALID 。
以下是谷歌对这个错误的说明(https://support.google.com/chrome/a/answer/7391219?hl=zh-Hans)

解决subjectAlternativeName 找不到的问题


所以需要先解决这个问题,以下为解决步骤:
主要修改在openssl.cnf(该文件在bin文件中)
确保req下存在以下2行(默认第一行是有的,第2行被注释了)
 

[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req

确保req_distinguished_name下没有 0.xxx 的标签,有的话把0.xxx的0. 去掉
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = ShangHai
localityName = Locality Name (eg, city)
localityName_default = ShangHai
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Domain Control Validated
commonName = Internet Widgits Ltd
commonName_max = 64

新增最后一行内容 subjectAltName = @alt_names(前2行默认存在)
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

新增 alt_names,注意括号前后的空格,DNS.x 的数量可以自己加
[ alt_names ]
DNS.1 = abc.example.com
DNS.2 = dfe.example.org
DNS.3 = ex.abcexpale.net
DNS.4 = localhost


以上是为了添加‘使用者备用名称(DNS)’,在下面的命令中会用到v3_req 也就是这几个DNS,证书里面才会多一个‘使用者备用名称’,如图:

借鉴:http://blog.51cto.com/colinzhouyj/1566438

客户端


生成私钥(key文件):

openssl genrsa -out client.key 2048


生成csr文件:

openssl req -new -key client.key -out client.csr -config openssl.cnf


这里需要填写一些基本信息:

服务器端


生成私钥(key文件):

openssl genrsa -out server.key 2048


生成csr文件

openssl req -new -key server.key -out server.csr -config openssl.cnf


这里的Common Name 写主要域名就好了(注意:这个域名也要在openssl.cnf的DNS.x里)
 

CSR文件必须有CA的签名才可形成证书.可将此文件发送到verisign等地方由它验证,要交一大笔钱,何不自己做CA呢.
1、在bin目录下新建目录 demoCA、demoCA/certs、demoCA/certs、demoCA/newcerts
2、在demoCA建立一个空文件 index.txt
3、在demoCA建立一个文本文件 serial, 没有扩展名,内容是一个合法的16进制数字,例如 0000
4、生成ca.key并自签署

openssl req -new -x509 -days 3650 -keyout ca.key -out ca.crt -config openssl.cnf
用生成的CA的证书为刚才生成的server.csr,client.csr文件签名:
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -extensions v3_req -config openssl.cnf
 
openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key -extensions v3_req -config openssl.cnf


到这里证书就生成好了
  


5.xca使用


  参考https://blog.csdn.net/chancein007/article/details/27239605


xca简介


  一般情况下,大家能想到管理和生成SSL证书的方法就是OpenSSL程序或者用JDK自带的keytool命令,但是这两种工具虽然功能强大,但是用户的可操作性并不好,需要用户记住并输入一些命令,而且也不是特别的直观。那么有没有一个好的证书管理工具,能帮我们方便的管理证书,方便的生成证书请求,方便的对证书进行自签名,方便的把证书以一种格式导入进来,然后以自己想要的另外一种格式导出去呢?答案就是,XCA(X Certificate and key management),XCA是一个开源的工具,底层还是基于openSSL的类库和API的。


xca安装步骤

Step1 . 打开浏览器,输入下载地址

Step2 . 然后点击“direct link” 或者 "mirror"标签,下载最新的版本,最新的版本是:1.3.2

Step3. 安装下载后的exe文件

Step4. 这样在你的开始菜单中,就能找到xca的目录,打开xca的程序即可。

xca使用


Step1. 打开XCA


Step2. 如果是第一次打开,请点击 File-->New Database


Step3. 选择证书数据存储的位置并命名存储文件的名字。


Step4. 设置密码保护证书数据

Step5: 鼠标点击到“Certificate Signing Request” 分页,并点击右边的“New Request”,将弹出下面的窗体。

Step6. 生成保护证书的秘钥:因为我们是生成证书请求,那么我们需要生成一个证书对,即私钥和公钥,上面Step6生成的信息是在公钥中可以看到的。

好了,使用XCA生成SSL证书请求的介绍就完成了,如果你还有其他的问题,请给我在文章后面留言,我将会尽可能在第一时间回复。


6.单向认证和双向认证


 单向认证:只需要验证SSL服务器身份,不需要验证SSL客户端身份。

双向认证:要求服务器和客户端双方都有证书,客户端需要校验服务端,服务端也需要校验客户端。

SSL双向认证和SSL单向认证的区别

  双向认证 SSL 协议要求服务器和用户双方都有证书。单向认证 SSL 协议不需要客户拥有CA证书,具体的过程相对于上面的步骤,只需将服务器端验证客户证书的过程去掉,以及在协商对称密码方案,对称通话密钥时,服务器发送给客户的是没有加过密的(这并不影响 SSL 过程的安全性)密码方案。这样,双方具体的通讯内容,就是加过密的数据,如果有第三方攻击,获得的只是加密的数据,第三方要获得有用的信息,就需要对加密的数据进行解密,这时候的安全就依赖于密码方案的安全。而幸运的是,目前所用的密码方案,只要通讯密钥长度足够的长,就足够的安全。这也是我们强调要求使用128位加密通讯的原因。

  一般Web应用都是采用SSL单向认证的,原因很简单,用户数目广泛,且无需在通讯层对用户身份进行验证,一般都在应用逻辑层来保证用户的合法登入。但如果是企业应用对接,情况就不一样,可能会要求对客户端(相对而言)做身份验证。这时就需要做SSL双向认证。

7.免费证书申请

 

  • https://www.pianyissl.com/order/info?id=136914
  • https://freessl.cn/
  • 阿里云上也有赛门铁克的免费证书,可以申请

8.单tomcat下配置https和wss


方案1


   修改tomcat配置
 

   


方案2

public EmbeddedServletContainerFactory createEmbeddedServletContainerFactory() throws IOException, NoSuchAlgorithmException  
    {  
        TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();  
        tomcatFactory.addConnectorCustomizers(new UKeFuTomcatConnectorCustomizer(maxthread, maxconnections));  
        File sslFile = new File(path , "ssl/https.properties") ;
        if(sslFile.exists()){
            Properties sslProperties = new Properties();
            FileInputStream in = new FileInputStream(sslFile);
            sslProperties.load(in);
            in.close();
            if(!StringUtils.isBlank(sslProperties.getProperty("key-store")) && !StringUtils.isBlank(sslProperties.getProperty("key-store-password"))){
                Ssl ssl = new Ssl();
                ssl.setKeyStore(new File(path , "ssl/"+sslProperties.getProperty("key-store")).getAbsolutePath());
                ssl.setKeyStorePassword(UKTools.decryption(sslProperties.getProperty("key-store-password")));
                tomcatFactory.setSsl(ssl);
            }
        }
        return tomcatFactory;  
    } 


9.nginx+tomcat下配置半链路https和wss


部署说明


chrome和nginx之间使用https和wss,nginx和tomcat之间依然使用http和ws


nginx 配置

 
upstream x.com.cn {
        session_sticky;
        server 10.115.88.2:3230 max_fails=3 fail_timeout=10s;
        server 10.115.88.3:3231 max_fails=3 fail_timeout=10s;
        server 10.115.88.4:3230 max_fails=3 fail_timeout=10s;
}
upstream x.com.cn.ws {
        server 10.115.88.2:9081 max_fails=3 fail_timeout=10s;
        server 10.115.88.3:9081 max_fails=3 fail_timeout=10s;
        server 10.115.88.4:9081 max_fails=3 fail_timeout=10s;
}
server {
       listen          80;
       server_name     you.com;
        listen 443 ssl http2 spdy;
        ssi  on;
        ssi_silent_errors on;
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect  off;
        proxy_redirect http:// $scheme://;
        proxy_set_header X-Forwarded-Proto  $scheme;
        ssl_certificate         /server.crt;
        ssl_certificate_key     /server.key;
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_session_tickets on;
        ssl_session_ticket_key /app/tengine/uat/key/tls_session_ticket.key;
        keepalive_timeout 75s;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv3;
        ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
        ssl_prefer_server_ciphers on;
        resolver 114.114.114.114;
        ssl_dhparam /dhparam.pem;
       if ($scheme = http) {
               return 301 https://$server_name$request_uri;
       }

       location / {
            proxy_set_header        Host $host;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header        X-Forwarded-Proto $scheme;
            proxy_redirect  off;
            proxy_pass http://x.com.cn;
       }
}
server {
       server_name      you.com;
       listen 443 ssl http2 spdy;
        ssi  on;
        ssi_silent_errors on;
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect  off;
        proxy_redirect http:// $scheme://;
        proxy_set_header X-Forwarded-Proto  $scheme;
        ssl_certificate         /server.crt;
        ssl_certificate_key     /server.key;
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_session_tickets on;
        ssl_session_ticket_key /app/tengine/uat/key/tls_session_ticket.key;
        keepalive_timeout 75s;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv3;
        ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
        ssl_prefer_server_ciphers on;
        resolver 114.114.114.114;
        ssl_dhparam /dhparam.pem;
       location / {
            proxy_set_header        Host $host;
            proxy_set_header        X-Real-IP $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header        X-Forwarded-Proto $scheme;
            proxy_http_version 1.1;
            proxy_set_header        Upgrade $http_upgrade;
            proxy_set_header        Connection "upgrade";
            proxy_redirect          off;
            proxy_pass              http://x.com.cn.ws;
       }
}
 


10.nginx+tomcat下配置全链路https和wss


 


11.uat 环境如何使用免费证书


   uat环境更换域名为x.com.cn,使用正式证书,在nginx上配置,然后本地配置host,进行测试


12.代码优化项

 

  • socketio请求,使用js进行http或者https适配

  • 图片请求,修改为//,使可以自动适配,包含访客头像,消息里的图片

  • 表情处理,表情显示在聊天窗口也是以图片显示的

  • 代码中使用request.getScheme()、request.getRequestURL() 会获取到的是 HTTP

  • Nginx 域名 HTTP 请求 302 跳转实现全站 HTTPS

  • iframe里的redirect处理,需要强制返回https


/**
 * 重写sendRedirect方法。http强制为https
 *
 */
public class HttpsServletResponseWrapper extends HttpServletResponseWrapper {
    private final HttpServletRequest request;
    public HttpsServletResponseWrapper(HttpServletRequest request2,HttpServletResponse response) {
        super(response);
        this.request=request2;
    }

    @Override
    public void sendRedirect(String location) throws IOException {
        if(location.startsWith("http://")||location.startsWith("https://")){
            //绝对路径,直接跳转。
            super.sendRedirect(location);
            return;
        }
        
        //假设前端请求头为http_https_scheme,可以传入的值有http或https,不传默认为https。
        if(("http").equals(request.getHeader("http_https_scheme"))){
            //http请求,默认行为。
            super.sendRedirect(location);
            return;
        }
        
        // 收集请求信息,为拼接绝对地址做准备。
        String serverName = request.getServerName();
        int port = request.getServerPort();
        String contextPath = request.getContextPath();
        String servletPath = request.getServletPath();
        String queryString = request.getQueryString();

        // 拼接绝对地址
        StringBuilder absoluteUrl = new StringBuilder();
        // 强制使用https
        absoluteUrl.append("https").append("://").append(serverName);
        //80和443位http和https默认接口,无需拼接。
        if (port != 80 && port != 443) {
            absoluteUrl.append(":").append(port);
        }
 
        // 将相对地址加入。
        absoluteUrl.append(location);
 
        // 跳转到绝对地址。
        super.sendRedirect(absoluteUrl.toString());
    }
}
 


13.参考资料


http://baike.baidu.com/view/7615.htm?fr=aladdin

http://www.ibm.com/developerworks/cn/security/se-pkiusing/index.html?ca=drs

http://www.ibm.com/developerworks/cn/security/s-pki/

http://en.wikipedia.org/wiki/X.509

http://zh.wikipedia.org/wiki/PKCS

http://blog.csdn.net/rztyfx/article/details/6919220

http://weekend.blog.163.com/blog/static/7468958201131591422649/

http://linux.chinaunix.net/techdoc/beginner/2009/06/29/1120721.shtml

http://www.360doc.com/content/12/0414/19/3725126_203594495.shtml

http://blog.sina.com.cn/s/blog_436fe8b10100r5p3.html

http://blog.csdn.net/allwtg/article/details/4982507

http://rhythm-zju.blog.163.com/blog/static/310042008015115718637/

http://www.mike.org.cn/articles/ubuntu-config-apache-https/
 

你可能感兴趣的:(socketio,在线客服,websocket)