• CocoaHttpServer设置https


    热烈欢迎,请直接点击!!!

    进入博主App Store主页,下载使用各个作品!!!

    注:博主将坚持每月上线一个新app!!!

    客户端向服务器发起需求 ,服务器把证书发给客户端,客户端验证下证书是否合法,然后用证书的数据加密传输数据给服务器,服务器解密

    生成证书步骤

    // 第一步,为服务器端和客户端准备公钥、私钥
    # 生成服务器端私钥
    openssl genrsa -out server.key 1024
    # 生成服务器端公钥
    openssl rsa -in server.key -pubout -out server.pem
    
    // 第二步,生成 CA 证书
    # 生成 CA 私钥
    openssl genrsa -out ca.key 1024
    openssl rsa -in ca.key -pubout -out ca.pem
    # X.509 Certificate Signing Request (CSR) Management.
    openssl req -new -key ca.key -out ca.csr
    # X.509 Certificate Data Management.
    openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
    
    // 第三步,生成服务器端证书
    # 服务器端需要向 CA 机构申请签名证书,在申请签名证书之前依然是创建自己的 CSR 文件
    openssl req -new -key server.key -out server.csr
    # 向自己的 CA 机构申请证书,签名过程需要 CA 的证书和私钥参与,最终颁发一个带有 CA 签名的证书
    openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
    
    // 第四步,生成cer文件
    # 使用openssl 进行转换
    openssl x509 -in server.crt -out server.cer -outform der
    openssl x509 -in ca.crt -out ca.cer -outform der
    
    // 将证书导出成浏览器支持的.p12格式,记得导出密码
    openssl pkcs12 -export -clcerts -in server.pem -inkey server.key -out server.p12

    在第二步时会出来一个填写资料的界面:

    Country Name (2 letter code) [AU]:CN
    State or Province Name (full name) [Some-State]:Guangdong
    Locality Name (eg, city) []:Shenzhen
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:cnblogs
    Organizational Unit Name (eg, section) []:strengthen
    Common Name (e.g. server FQDN or YOUR name) []:localhost
    Email Address []:newsagency@163.com

    配置服务器

    为了方便,我是以mac本地电脑做服务器,使用的是XAMPP搭建的服务器使用的是apache。在其他服务器上应该就是文件路径位置不一样,其他应该是一样的。如果有些服务器没开启ssl,可以网上搜索怎么开启。

    修改httpd-ssl.conf文件 把server.crt和server.key的路径修改对就好了
    SSLCertificateFile /apache/conf/server.crt  
    SSLCertificateKeyFile /apache/conf/server.key 

    文件里设置一下开启 https 功能:

     
    - (BOOL)isSecureServer
    {
     
        // Create an HTTPS server (all connections will be secured via SSL/TLS)
        return YES;
    }
     
    /**
     * This method is expected to returns an array appropriate for use in kCFStreamSSLCertificates SSL Settings.
     * It should be an array of SecCertificateRefs except for the first element in the array, which is a SecIdentityRef.
     **/
    - (NSArray *)sslIdentityAndCertificates
    {
        SecIdentityRef identityRef = NULL;
        SecCertificateRef certificateRef = NULL;
        SecTrustRef trustRef = NULL;
     
        NSString *thePath = [[NSBundle mainBundle] pathForResource:@"my" ofType:@"p12"];
        NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
        CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
        CFStringRef password = CFSTR("123");
        const void *keys[] = { kSecImportExportPassphrase };
        const void *values[] = { password };
        CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
        CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
     
        OSStatus securityError = errSecSuccess;
        securityError =  SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
        if (securityError == 0) {
            CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
            const void *tempIdentity = NULL;
            tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
            identityRef = (SecIdentityRef)tempIdentity;
            const void *tempTrust = NULL;
            tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
            trustRef = (SecTrustRef)tempTrust;
        } else {
            NSLog(@"Failed with error code %d",(int)securityError);
            return nil;
        }
     
        SecIdentityCopyCertificate(identityRef, &certificateRef);
        NSArray *result = [[NSArray alloc] initWithObjects:(id)CFBridgingRelease(identityRef),   (id)CFBridgingRelease(certificateRef), nil];
     
        return result;
    }

    总结一下配置过程中可能碰到配置完成后还是无法访问https的问题:

    1、可以判断p12文件是否导入项目,以及路径是否寻找正确

    2、确保iOS项目中代码所有的请求都为https请求,因为ssl配置服务器的时候,如果服务器中含有http请求,同样会出现不安全的ssl情况

    3、在GCDAsyncSocket.m文件中注释该段代码

    //    if (value)
    //    {
    //        NSAssert(NO, @"Security option unavailable - kCFStreamSSLLevel"
    //                     @" - You must use GCDAsyncSocketSSLProtocolVersionMin & GCDAsyncSocketSSLProtocolVersionMax");
    //
    //        [self closeWithError:[self otherError:@"Security option unavailable - kCFStreamSSLLevel"]];
    //        return;
    //    }

    配置AFNetworking

    + (AFSecurityPolicy*)customSecurityPolicy
    {
        // /先导入证书
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];//证书的路径
        NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    
        // AFSSLPinningModeCertificate 使用证书验证模式
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    
        // allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
        // 如果是需要验证自建证书,需要设置为YES
        securityPolicy.allowInvalidCertificates = YES;
    
        //validatesDomainName 是否需要验证域名,默认为YES;
        //假如证书的域名与你请求的域名不一致,需把该项设置为NO;如设成NO的话,即服务器使用其他可信任机构颁发的证书,也可以建立连接,这个非常危险,建议打开。
        //置为NO,主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
       //如置为NO,建议自己添加对应域名的校验逻辑。
        securityPolicy.validatesDomainName = NO;
    
        securityPolicy.pinnedCertificates = @[certData];
    
        return securityPolicy;
    }
    
    + (void)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
    {
        // 1.获得请求管理者
        AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
        // 2.申明返回的结果是text/html类型
        mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
    
        // 加上这行代码,https ssl 验证。
        [mgr setSecurityPolicy:[NetworkHelpManager customSecurityPolicy]];
    
        // 3.发送POST请求
        [mgr POST:url parameters:params
      success:^(NSURLSessionDataTask *operation, id responseObj) {
              if (success) {
                success(responseObj);
             }
          } failure:^(NSURLSessionDataTask *operation, NSError *error) {
              if (failure) {
                  failure(error);
              }
          }];
    }

    info.plist,配置白名单

    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <false/>
        <key>NSExceptionDomains</key>
        <dict>
            <key>cer文件中查看</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSExceptionMinimumTLSVersion</key>
                <string>TLSv1.0</string>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
  • 相关阅读:
    经济学原理---10 外部性-- 读书笔记
    经济学原理---9应用:国际贸易--- 读书笔记
    人月神话阅读笔记之一
    小水王
    构建之法读书笔记之五
    课堂作业
    时间记录日志
    构建之法读书笔记之四
    查找水王程序
    代码阅读方法与实践阅读笔记01
  • 原文地址:https://www.cnblogs.com/strengthen/p/16090920.html
Copyright © 2020-2023  润新知