美文网首页我爱编程
OpenSSL 签发私有CA证书,解决IE无法使用跨域ajax调

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

作者: rekeer | 来源:发表于2018-06-07 10:19 被阅读0次

    问题描述

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

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

    制作私有到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. 配置内容如下:

          <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                     maxThreads="150" SSLEnabled="true">
              <SSLHostConfig>
                  <Certificate certificateKeystoreFile="E:/ssl/mycompany.com.p12"
                               type="RSA" certificateKeystoreType="PKCS12" certificateKeystorePassword="123456"/>
              </SSLHostConfig>
          </Connector>
      
    4. 浏览器访问时,证书是属于受信任的证书,不会在弹出安全提示

    5. 服务端代码

          @ResponseBody
          @RequestMapping("/getinfo")  
          public String getinfo(HttpServletRequest request,HttpServletResponse response){
              Map<String,String> map = new HashMap<String,String>();
              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调

        本文链接:https://www.haomeiwen.com/subject/kxiwsftx.html