OpenSSL 签发私有CA证书,解决IE无法使用跨域ajax调用问题

问题描述

”XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成”错误,chrome、firefox和Safari等ssl和非ssl没有问题,但是IE在使用ssl时会出现以上错误(前置条件使用cros方式解决ajax跨域问题)

使用openssl制作myrootca证书准备及环境mycompany

  • win10 64
  • 下载[http://slproweb.com/products/Win32OpenSSL.html][opensslwin64],版本Win64 OpenSSL v1.1.0h Light
  • 按照默认选项进行安装到window中

制作私有到CA受信任证书

  1. 默认安装到地址window主机中,配置环境变量C:\OpenSSL-Win64\bin\至path
  2. 准备生成OpenSSL文件夹,以生成根证书及服务器证书
  • 新建文件夹E:\sslca
  • 将C:\OpenSSL-Win64\bin\openssl.cfg放到E:\sslca中
  1. 修改openssl.cfg配置文件,配置CA证书生成内容及版本等信息

    • 将eq_extensions = v3_req的#取消
    req_extensions = v3_req # The extensions to add to a certificate request
    
    • 在[ v3_req ]加入subjectAltName = @alt_names
    [ v3_req ]
    # Extensions to add to a certificate request
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName = @alt_names
    [ alt_names ]
    DNS.1 = mycompany.com
    DNS.2 = *.mycompany.com
    
  • 加入[ alt_names ]值,为谁签发证书,注意括号前后的空格,DNS.x 的数量可以自己加, 这里的DNS就是你网站的地址,效果如下
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = mycompany.com
DNS.2 = *.mycompany.com

  • 修改证书默认路径,原来dir = ./demoCA,修改为如下

      [ CA_default ]
    dir     = ./rootCA      # Where everything is kept
    和
    [ tsa_config1 ]
    # These are used by the TSA reply generation only.
    dir     = ./rootCA      # TSA root directory
    
  1. 在E:\sslca生成必要的文件夹,以便生成CA跟证书,(这些文件和文件夹是 openssl.cfg 要求的)

    • 进入E:\sslca
    • 执行以下命令
    > mkdir rootCA\private rootCA\newcerts
    > type nul > rootCA\index.txt
    > echo 01 > rootCA\serial
    
  2. 生成CA自签名跟证书,用户导入系统,负责系统信任(如CA证书提前导入相同)

  • 生产RootCA证书,进入进入E:\sslca执行
  > openssl req -new -x509 -newkey rsa:2048 -days 3650 -keyout rootCA\private\MyRootCA.key -out rootCA\MyRootCA.crt -passout pass:123456 -config openssl.cfg

命令说明:

参数                  | 描述
---------------------| ---------------------
-days 3650           | 根证书的有效期是 10年
-passout pass:123456 | CA的密钥是 123456
-config openssl.cfg  | 使用当前文件夹的openssl.cfg作为默认设置, 如果不使用这个命令的话, 将使用C:\OpenSSL-Win64\bin \openssl.cfg

控制台输出:

Generating a 2048 bit RSA private key
..............................................+++
.......................+++
writing new private key to 'rootCA\private\MyRootCA.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BeiJing
Locality Name (eg, city) []:BeiJing
Organization Name (eg, company) [Internet Widgits Pty Ltd]:mycompanya
Organizational Unit Name (eg, section) []:mycompany.com
Common Name (e.g. server FQDN or YOUR name) []:MyRootCA
Email Address []:
  1. 生产用户证书
  • 生产用户RSA秘钥对
>openssl genrsa -des3 -out mycompany.com.key -passout pass:123456

控制台输出:

Generating RSA private key, 2048 bit long modulus
.............+++
.............................................+++
e is 65537 (0x010001)
  • 根据秘钥对生成用户证书
>openssl req -new -days 3650 -key mycompany.com.key -out mycompany.com.csr -config openssl.cfg

控制台输出,输入密码时看不到输入,其实已经输入,另外下面中的Country Name、Some-State、company必须与MyRootCA一致, 原因:

openssl.cfg中有这样一段, 当然你可以按需修改

```
[ policy_match ]
 countryName     = match                    #证书请求与证书本身一样
 stateOrProvinceName = match                #证书请求与证书本身一样
 organizationName    = match                #证书请求与证书本身一样
 organizationalUnitName  = optional         #可选项
 commonName      = supplied                 #证书请求中必须能存在该项
 emailAddress        = optional             #可选项
``` 

控制台输出 :

Enter pass phrase for mycompany.com.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BeiJing
Locality Name (eg, city) []:BeiJing
Organization Name (eg, company) [Internet Widgits Pty Ltd]:mycompanya
Organizational Unit Name (eg, section) []:mycompany.com
Common Name (e.g. server FQDN or YOUR name) []:mycompany.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
  1. 使用CA证书签发用户证书,如果此处的用户证书和rootCA证书CN等信息不匹配,则无法生成证书

    >openssl ca -in mycompany.com.csr -out mycompany.com.crt -cert rootCA\MyRootCA.crt -keyfile rootCA\private\MyRootCA.key -extensions v3_req -config openssl.cfg
    

控制台输出:

```
Using configuration from openssl.cfg
Enter pass phrase for rootCA\private\MyRootCA.key:
Can't open ./rootCA/index.txt.attr for reading, No such file or directory
14380:error:02001002:system library:fopen:No such file or directory:crypto\bio\bss_file.c:74:fopen('./rootCA/index.txt.attr','r')
14380:error:2006D080:BIO routines:BIO_new_file:no such file:crypto\bio\bss_file.c:81:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: May 17 03:13:48 2018 GMT
            Not After : May 17 03:13:48 2019 GMT
        Subject:
            countryName               = CN
            stateOrProvinceName       = BeiJing
            organizationName          = mycompanya
            organizationalUnitName    = mycompany.com
            commonName                = mycompany.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Subject Alternative Name:
                DNS:mycompany.com, DNS:*.mycompany.com, DNS:*.uuu.mycompany.com, DNS:*.sss.mycompany.com, DNS:auth.uuu.mycompany.com
Certificate is to be certified until May 17 03:13:48 2019 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
```

注意:如果出现./rootCA/newcerts is not a directory需要修改openssl.cfg文件,将rootCA修改为自定义的rootCA目录,前边有讲述如何设置

  1. 生产p12证书,用于web服务器设置

    >openssl pkcs12 -export -inkey mycompany.com.key -in mycompany.com.crt -out mycompany.com.p12
    

控制台输出:

```
Enter pass phrase for mycompany.com.key:
Enter Export Password:
Verifying - Enter Export Password:
```

证书必要说明

  1. 为什么用户证书的CN、SiChuan、YourCompany必须与MyRootCA一致?

    openssl.cfg中有这样一段, 当然你可以按需修改

    [ policy_match ]
     countryName     = match                    #证书请求与证书本身一样
     stateOrProvinceName = match                #证书请求与证书本身一样
     organizationName    = match                #证书请求与证书本身一样
     organizationalUnitName  = optional         #可选项
     commonName      = supplied                 #证书请求中必须能存在该项
     emailAddress        = optional             #可选项
    

证书验证

  1. 将RootCA证书安装到受信任的根证书颁发机构,首先安装RootCA证书,否则用户证书是不被信任的跟证书(安装到本地受信任的根证书颁发机构,安装过程请自行查找)

  2. 在Tomcat8.5中的server.xml中加入证书配置

  3. 配置内容如下:

        
            
                
            
        
    
  4. 浏览器访问时,证书是属于受信任的证书,不会在弹出安全提示

  5. 服务端代码

        @ResponseBody
        @RequestMapping("/getinfo")  
        public String getinfo(HttpServletRequest request,HttpServletResponse response){
            Map map = new HashMap();
            map.put("result", "hh");
            Cookie[] cookies = request.getCookies();
            if(null != cookies){
                for (int i = 0; i < cookies.length; i++) {
                    Cookie cookie = cookies[i];
                    System.out.println(cookie.getDomain() + "  "+ cookie.getName()+ "  "+ cookie.getPath()+ "  "+ cookie.getValue() );
                }
            }
            response.addHeader("Set-Cookie", "id="+request.getSession().getId()+"; Domain=.mycompany.com; Path=/");
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
            response.setHeader("Access-Control-Allow-Methods", "POST, GET");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    
            return "hello";  
        }  
    
  6. 请求端代码

        jQuery.support.cors = true//加入jQuery.support.cors = true和crossDomain:true,成对加,火狐和google不可以
        $('#CORS').click(function (){
            $.ajax({
              url: "https://common.mycompany.com:8443/app1/getinfo",
             crossDomain:true,
             xhrFields: {//加上此处,火狐、chrome、ie7-11都可以,不需要crossDomain:true,和jQuery.support.cors = true
                withCredentials: true
            },
              success: function(html){
                  console.log(html);
                  console.log(document.cookie);
              }
            });
        })
    

浏览器验证

  1. IE浏览器

    默认仿真器为IE7,测试时会弹出alert警告框,IE8、9仿真器可通过,IE10、11出现错误:

    SEC7120: 在 Access-Control-Allow-Origin 标头中未找到源 https://java.mycompany.com:8444。

    SCRIPT7002: XMLHttpRequest: 网络错误 0x80700013, 由于出现错误 80700013 而导致此项操作无法完成。

    XMLHttpRequest: Network Error 0x80700013, Could not complete the operation due to error 80700013.

    解决方法:Internet选项-安全,添加受信任站点(使用ajax的网站,而非ajax调用的网站,当然都加上也可以),同时将受信任站点安全级别调整到最低,IE7、8、9、10、11的问题都可以解决

  2. 火狐浏览器

    在window安装完证书后IE可以成功,但是火狐还是会出现https安全提示,请求ajax连接时出现以下错误:

    common.mycompany.com:8443 使用了无效的安全证书。该证书因为其颁发者证书未知而不被信任。该服务器可能未发送相应的中间证书。可能需要导入额外的根证书。错误代码: SEC_ERROR_UNKNOWN_ISSUER

    解决方法:进入火狐浏览器的设置界面,选择 高级→证书→查看证书→证书机构→导入,将RootCA证书导入到火狐中即可(火狐和ie等不是使用同一套CA认证证书,在火狐浏览器中单独管理)

  3. chrome浏览器

    chrome浏览器没有问题

  4. safari浏览器

    safari浏览器没有问题,在mac系统中需要将RootCA证书安装到系统中,并且进行信任证书(双击证书-证书-点击对应证书-信任)。

可解决的问题

1.ajax调用时提示错误,原因实际上发现IE根本就没把请求发送出去, 所以可以说是IE截断了请求, 具体原因应该是和证书有关系, 因为CA颁发的证书就不存在该问题

SCRIPT7002: XMLHttpRequest: network error 0x2ef3

XMLHttpRequest: 网络错误 0x2ef3, 由于出现错误 00002ef3 而导致此项操作无法完成

你可能感兴趣的:(OpenSSL 签发私有CA证书,解决IE无法使用跨域ajax调用问题)