基于Nodejs创建https服务

为什么用https服务

关于https协议和相关加密算法,请参考我的另一篇:HTTPS详解SSL/TLS。很多情况下,为了保证服务器的安全,比如我在服务端搭建了一个rest服务,这时候如果采用http的协议,很不安全,大部分的做法是http+web json token,但是对于token的处理也是比较棘手的。如果是对外提供开放接口,比如像百度、腾讯这些第三方开放平台接口,比如登录授权这些,可以采用http+OAuth2.0解决。对于自己做得服务器来说,如果涉及到支付交易这些,后台采用HTTPS+session的做法比较好。

皓眸大前端开发学习

转载请注明出处:http://www.haomou.net/2014/10/18/2014_https_node/

HTTP和HTTPS介绍

HTTP: 超文本传输协议 (HTTP-Hypertext transfer protocol) 是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。

HTTPS:(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司进行,提供了身份验证与加密通讯方法,现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。

HTTPS和HTTP的区别

  1. https协议需要到ca申请证书,一般免费证书很少,需要交费。
  2. http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
  3. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  4. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTP和HTTPS的介绍,摘自http://baike.baidu.com/view/14121.htm

在Nodejs中,我们可以通过内置的https库,来实现HTTPS服务器。

Nodejs的HTTPS使用文档:http://nodejs.org/api/https.html

基于nodejs搭建https服务器

搭建https服务器首先要安装openssl,用于生成证书。如果你已经安装了git客户端msysgit,这个其中包括了openssl程序。

1
2
3
4
5
6
7
8
9
10
11
12
~ D:\workspace\javascript\nodejs-https>git --version
git version 1.8.1.msysgit.1
~ D:\workspace\javascript\nodejs-https>openssl version -a
OpenSSL 0.9.8e 23 Feb 2007
built on: Sat Sep 15 20:34:58 EDT 2007
platform: MSys
options: bn(64,32) md2(int) rc4(idx,int) des(ptr,risc1,16,long) blowfish(idx)
compiler: gcc -D_WINDLL -DOPENSSL_PIC -DOPENSSL_THREADS -DDSO_DLFCN -DHAVE_DLFCN_H -DTERMIOS -DL_ENDIAN -D__CYGWIN__ -f
omit-frame-pointer -fnative-struct -O3 -mcpu=pentium -march=i486 -Wall -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -
DSHA1_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM
OPENSSLDIR: "/usr/ssl"

使用openssl生成证书文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#生成私钥key文件:
~ D:\workspace\javascript\nodejs-https>openssl genrsa -out privatekey.pem 1024
Generating RSA private key, 1024 bit long modulus
...........................++++++
........++++++
e is 65537 (0x10001)
#通过私钥生成CSR证书签名
~ D:\workspace\javascript\nodejs-https>openssl req -new -key privatekey.pem -out certrequest.csr
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]:fens.me
Organizational Unit Name (eg, section) []:fens.me
Common Name (eg, YOUR name) []:Conan Zhang
Email Address []:bsspirit@gmail.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
# 通过私钥和证书签名生成证书文件
~ D:\workspace\javascript\nodejs-https>openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
Signature ok
subject=/C=CN/ST=Beijing/L=Beijing/O=fens.me/OU=fens.me/CN=Conan Zhang/emailAddress=bsspirit@gmail.com
Getting Private key

新生成了3个文件:certificate.pem, certrequest.csr, privatekey.pem

1
2
3
privatekey.pem: 私钥
certrequest.csr: CSR证书签名
certificate.pem: 证书文件

修改app.js

1
2
3
4
5
6
7
8
9
10
11
12
//最末尾处添加
var https = require('https')
,fs = require("fs");
var options = {
key: fs.readFileSync('./privatekey.pem'),
cert: fs.readFileSync('./certificate.pem')
};
https.createServer(options, app).listen(443, function () {
console.log('Https server listening on port ' + 3011);
});

启动服务器:

1
2
3
~ D:\workspace\javascript\nodejs-https>node app.js
Https server listening on port 443

HTTPS访问时会出出现下面的提示:
皓眸大前端开发学习
这个是因为我们自己生成的证书并不是认证过的,无法确定是合法有效的。

抓取请求,验证加密

为了验证数据在传输过程中是加密的,我们用wireshark抓取网络包。
抓取HTTP请求:http://192.168.1.20/users?a=111 ,结果如下:

皓眸大前端开发学习
抓取HTTPS请求:https://192.168.1.20/users?a=112 ,结果如下:

皓眸大前端开发学习

在HTTP下面,URL请求的参数是被暴露的。在HTTPS下面,URL的请求参数是被加密的。因此,希望需要填写个人信息,及在线支付的网站,都把HTTPS服务器搭建起来。防止私密数据,在网络传输过程中被获取。

使用http-server

还有一种搭建https服务器的简便方法,就是使用http-server插件,先安装http-server:

1
npm install -g http-server

然后制作公私钥文件(cert.csr,cert.pem,key.pem),将这三个文件拷贝到要部署的项目根目录,然后再要开启https服务的项目根目录执行:

1
http-server . -S

即可。

谢谢!

转载请注明出处:http://www.haomou.net/2014/10/18/2014_https_node/

欢迎关注皓眸学问公众号(扫描左侧二维码),每天好文、新技术!任何学习疑问或者工作问题都可以给我留言、互动。T_T 皓眸大前端开发学习 T_T