美文网首页张蕾的技术博客前端
【从简】Express Generator搭建HTTPS前端框架

【从简】Express Generator搭建HTTPS前端框架

作者: SevenJustin | 来源:发表于2016-12-23 11:53 被阅读2987次

    Express是基于Node.js的前端Web开发框架, 其支持友好的API服务,因此我们可以借助Express来模拟API数据进行开发调试。

    安装

    1. 查看Node.js的版本
      node -v
      如果没有安装则先安装 可参考:安装Node.js 的Node安装部分

    2. 创建一个测试工程目录,存放Express项目框架
      npm install express-generator -g
      如果连接不上或速度慢可切回国内
      npm install -g cnpm --registry=https://registry.npm.taobao.org
      再执行
      cnpm install express-generator -g
      如果创建成功会出现目录位置如:

    link /usr/local/bin/express@ -> /usr/local/lib/node_modules/express-generator/bin/express

    3 接着就cd到你自己的路径 执行生产自己工程的目录
    express myApp
    后提示警告并选择继续

    warning: the default view engine will not be jade in future releases
    warning: use --view=jade or --help for additional options
    destination is not empty, continue? [y/N] y
    之后会有一个列表等待安装

    参考

    npm install 来安装上这些内容,工程中会多一个node_modules的文件夹,里面是所有依赖包文件。

    4 Express模板中的文件,其中bin文件夹下面的www.js文件是服务的启动文件,其中启动了HTTP的服务,默认端口为3000。routes文件夹下面的文件用于配置api路由,默认有index.js与users.js两个。app.js文件中对api进行了初始化与配置。可以在users.js中添加一个测试api如下:

    var express = require('express');
    var router = express.Router();
    
    /* 这个是默认生成的. */
    router.get('/', function(req, res, next) {
      res.send('respond with a resource');
    });
    /* 添加一个测试api*/
    router.get('/testAPi',function(rep,res,next){
      res.send('{name:jaki,age:24}');
    });
    module.exports = router;
    

    5 cd到自己工程目录下,通过Node启动Express 执行:node bin/www, 或者也可以通过:DEBUG=myappName npm start 来启动。如果服务启动成功就可以在浏览器输入http://127.0.0.1:3000/users/testAPi 会返回我们send()方法传递的字符串

    6 如果要取消
    MacOS系统在服务进行中,可以使用control+c来释放端口的监听,如果不小心使用control+z或者关闭了终端,会导致所监听端口的无法释放,下次如果再次启动node服务,会报Port 3000 is already in use的错误,可以使用如下方法来进行所监听端口的释放。首先使用如下命令查看所有监听某个端口的服务,例如3000端口:
    sudo lsof -i:3000
    会列出当前的进程信息:

    COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
    node 9184 ucsapp 13u IPv6 0xd256c96f6cc1477d 0t0 TCP *:hbci (LISTEN)

    在执行杀死这个监听:sudo kill -9 9184

    支持HTTPS

    搭建HTTPS服务需要有证书凭证,两种证书我们可以选择,一种是CA机构签发的证书,还有一种是我们自己制作的自签名证书.现在创建自签名证书,这里提供两种方法,测试第二种网页在信任完证书后可以正常访问:

    方法一:

    1 在Mac电脑上打开钥匙串访问应用,打开其中的证书助理

    1
    2
    证书的名字自定义,身份类型选择的是自签名的根证书,证书类型选择SSL服务器,之后点击创建即可完成证书的创建。

    2 从KeyChain中导出.p12文件并设置密码,那这个.p12文件其实是一个复合文件,其中包装了私钥与证书信息,使用OpenSSL工具可以将其中的信息进行提取,而搭建一个支持HTTPS的服务器是需要两个文件,分别问证书文件和私钥文件,下面我们来从.p12文件中提取这些需要的文件。

    3 从p12中提取证书和私钥 分别是导出密钥和证书对应nocerts nokeys,openssl导出过程中可能需要输入密码。

    openssl pkcs12 -in yourP12Path.p12 -nocerts -out yourPathOfPrivateKey.pem -nodes
    openssl pkcs12 -in yourP12Path.p12 -nokeys -out yourPathOfCert.pem -nodes
    

    方法二:

    1. openssl genrsa -des3 -out server.key 2048
    2. openssl req -new -key server.key -out server.csr
    3. cp /Users/xxx/Desktop/server.key server.key.org       
       openssl rsa -in server.key.org -out serverNew.key 
    4. openssl x509 -req -days 365 -in /Users/xxx/Desktop/server.csr -signkey /Users/xxx/Desktop/serverNew.key -out serverFinal.crt 
    

    4 将他们拷贝到你Express项目的bin文件夹下


    1

    5 在启动入口处即/bin/www文件里录入一下代码支持HTTPS

    /*
    HTTPS
    */
    var fs = require('fs');
    var https = require('https');
    /*
    密钥文件
    */
    var privatekey = fs.readFileSync('bin/privateKey.pem', 'utf8');  
    /*
    证书文件
    */
    var certificate = fs.readFileSync('bin/cert.pem', 'utf8');  
    var options={key:privatekey, cert:certificate};  
    var serverHttps = https.createServer(options, app);  
    /*
    绑定端口
    */
    serverHttps.listen(8080,function () {
        console.log('Https server listening on port ' + 8080);
    }); 
    

    6 node bin/www 启动并浏览器输入https://localhost:8080/users 因为我们改变了监听端口为8080,因为支持了https所以不再是http 接下来浏览器就会提示你是否信任该自签名的证书。就算成功告一段落了。

    7 付费从CA机构签发的证书是被默认信任的,则iOS工程无需做任何修改,只需将请求url改成https,像上面这种我们自签名的证书是会被默认拒绝访问,xCode会输出错误提示:NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802),。你可以调用试试看:

    -(void)checkThisHttps{
        
        NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://localhost:8080/users"]];
        NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession * session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];
        [[session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"%@,%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],error);
        }] resume];
    }
    
    1

    8 如果改成http 监听3000 后又发现xcode限制了http的访问,但我们可以通过设置NSAppTransportSecurity来绕过,其中NSAllowsArbitraryLoads是否允许所有不安全的请求,比如之一的http请求,默认为NO,因而我们又发现其下有一个NSExceptionDomains,里面有一个NSExceptionAllowsInsecureHTTPLoads,设置是否允许此域名使用自签名的证书进行请求,默认为NO,如果设置为YES,则在提交时需要说明原因。最好服务器都换成HTTPS协议的其实CA购买的那种证书免去信任验证问题,不然只能适配验证自签名的HTTPS证书了。

    9 在进行HTTPS请求时,服务器会将证书文件返回给客户端,如果客户端的证书信任列表中有这个证书,则此请求可以正常进行,否则请求会被拒。因此,因此我们只需要将自签名的证书安装进客户端的信任列表就可以了。iOS中需要使用的证书是der格式,所以我们将pem格式的证书转换成der格式的证书:

    openssl x509 -inform PEM -in cert.pem -outform DER -out cert.der
    

    然后将cert.der导入到iOS工程中,并设置NSURLSession的delegate为self后在回调用设置这个服务器中的证书文件对应的der证书为可信任就行了。自此HTTPS自签名证书在iOS的应用中就解决了,其实整个配置过程就是浏览器中选择信任该证书的代码体现而已。

    -(void)normalHttps{
        
        NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://localhost:8080/users"]];
        NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession * session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        [[session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            NSLog(@"%@,%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],error);
        }] resume];
    }
    
    - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
        
        NSLog(@"证书认证");
        
        //先判断证书是否有效
        if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) {
            
            //证书验证请求
            SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
            /**
             *  导入多张CA证书(Certification Authority,支持SSL证书以及自签名的CA)
             */
            NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"cert" ofType:@"der"];//自签名证书
            NSData* caCert = [NSData dataWithContentsOfFile:cerPath];
            if(!caCert) return;//读取证书文件失败
     
           //可以添加多张证书
            NSArray *caArray = @[caCert];
            //验证规则
            NSMutableArray *policies = [NSMutableArray array];
            [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()];
            SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
            NSMutableArray *pinnedCertificates = [NSMutableArray array];
            //进行自签名证书的添加
            for (NSData *certificateData in caArray) {
                [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)];
            }
            SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates);
            SecTrustResultType result = -1;
            //通过本地导入的证书来验证服务器的证书是否可信
            SecTrustEvaluate(serverTrust, &result);
            NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
            
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
            
            return [[challenge sender] useCredential: credential forAuthenticationChallenge: challenge];
        }
    }
    

    相关文章

      网友评论

        本文标题:【从简】Express Generator搭建HTTPS前端框架

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