4. HTTP
和HTTPS
的区分
-
HTTPS
服务器运用HTTPS
协定,HTTP
服务器运用HTTP
协定. -
HTTPS
服务器须要向证书受权(Certificate Authority)
中间要求证书,平常免费证书何绍须要交费.在少量读客户端有要求的情况下,也会要求客户端运用证书. -
HTTP
服务器于客户端之间传输的是明文数据,而HTTPS
服务器于客户端之间传输的是经由SSL
平安加密后的密文数据. -
HTTP
服务器一般运用80
或8080
端口,HTTPS
服务器运用443
端口.
5. 竖立HTTPS
服务器
5.1 前提条件——预备公钥私钥和证书
竖立HTTPS
服务器之间,服务器端起首须要竖立公钥,私钥及证书
- 竖立公钥,能够运用
openssl
东西竖立私钥openssl genrsa -out privatekey.pem 1024
- 竖立证书署名要求
(Certificate Signing Request)
文件openssl req -new -key privatekey.pem -out certreques.csr
- 猎取证书,证书应当是一个经由证书受权中间署名的文件,该证书文件内宝蓝了服务器端供应的公钥以及证书的颁布机构等信息
openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
,x509
代表该证书怎样国际电信同盟制订的数字证书规范
在客户端与服务器端竖立衔接后,将起首确认证书的合法性,假如在服务器中运用进修或测试用证书,运用浏览器接见该服务器时,浏览器中将先显现一个正告信息,正告用户该证书不是一个经由证书受权中间署名的证书.
在具有了证书文件以后,能够运用该证书文件竖立一个pfx
文件,所谓的pfx
文件,是指该文件内容必需相符公钥加密手艺12号规范(Public Key Cryptography Standards #12, PKCS#12)
为存储和传输用户或服务器私钥,公钥和证书而指定的花样.
+. 在openssl
东西中,能够竖立pfx
文件openssl pkcs12 -export -in certificate.pem -inkey privatekey.pem -out certificate.pfx
在这些文件都具有了以后,能够运用HTTPS
模块中的createServer
要领竖立一个HTTPS
服务器HTTPS.createServer(options, [requestListener(request, response)])
5.2 最先竖立HTTPS
服务器
HTTPS.createServer(options)
options
为一个对象,运用的属性及属性值以下所示-
pfx
: 属性值为一个字符串或一个Buffer
对象,用于指定从pfx
文件读掏出的私钥,公钥及证书,运用该属性值不须要指定key
属性值,cert
属性值以及ca
属性值. -
key
: 属性值为一个字符串或一个Buffer
对象,用于指定从后缀名为pem
的私钥文件中读掏出来的私钥,该属性值为必需指定属性值,除非指定了pfx
属性值 -
passphrase
: 属性值为一个自飞船,用于为私钥文件或pfx
文件指定暗码 -
cert
: 属性值为一个字符串或一个Buffer
对象,用于指定从后缀名为pem
的文件中读物出来的公钥,该属性值为必需指定属性值,除非指定了pfx
属性值 -
ca
: 属性值为一个字符串或一个Buffer
对象数组,用于指定一组证书,默许属性值为几个有名的证书受权认证中间,比方VerlSign
-
crl
: 属性值为一个字符串或一个Buffer
对象数组,用于指定证书撤消列表 -
ciphers
: 属性值为一个字符串值,用于形貌须要运用或作废运用的暗码.为了阻挠BEAST进击,引荐奖ciphers
属性与honorCipherOrder
属性连系运用,以指定非CBC(Cipher-block chaining,暗码分组链接)
形式的暗码优先级,默许属性值为AES128-GCM-SHA256: RC4: HIGH: !MD5: !aNULL: !EDH
-
handshakeTimeout
: 属性值为一个整数,用于指定若干秒内假如没有完成客户端与服务器之间的握手,则摒弃本次衔接,默许属性值为120s
.当在指定时间内没有完成握手时,将处分HTTPS
服务器的clientError
事宜. -
honorCipherOrder
: 属性值为一个布尔值,当属性值指定为true
时,服务器将暗码列表发送给客户端,有客户端挑选暗码,只管该属性值默许为false,然则仍引荐奖该属性值设置为true
,以阻挠BEAST
进击 -
requestCert
: 属性值为一个布尔值,当属性值指定为true
时,服务器在确认衔接时要求客户端供应证书,默许属性值为false
-
rejectUnauthorized
:属性值为一个布尔值,假如属性值为true
,那末服务器谢绝任何不能供应服务器端所要求的证书的客户端.只有当requestCert
属性值指定为true
时,该属性值才有用,默许属性值为false
-
NPNProtocols
: 属性值为一个数组或一个Buffer
对象,用于指定服务器端所需运用的NPN
协定(这些协定应当根据其优先级排序).NPN(Next Protocol Negotiation)
协定是一种用于指定服务器能够运用多种协定(包含HTTP,SPDY协定等)
的协定 -
sessionIdContext
: 属性值指定为true,那末默许属性值为一个MD5散列值,假如requestCert
属性值指定为false
,不供应默许属性值
-
5.3 竖立https
服务器
- 天生私钥key文件
openssl genrsa 1024 > /root/https/private.pem
- 经由过程私钥文件天生CSR证书署名
openssl req -new -key /root/https/private.pem -out csr.pem
- 经由过程私钥文件和CSR证书署名天生证书文件
openssl x509 -req -days 365 -in csr.pem -signkey /root/https/private.pem -out /root/https/file.crt
-
app.js
文件代码
let app = require('express')();
const fs = require('fs');
const http = require('http');
const https = require('https');
const privateKey = fs.readFileSync('/root/https/private.pem', 'utf8');
const certificate = fs.readFileSync('/root/https/file.crt', 'utf8');
const credentials = {key: privateKey, cert: certificate};
const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);
const PORT = 18080;
const SSLPORT = 18081;
httpServer.listen(PORT, function() {
console.log('HTTP Server is running on: http://localhost:%s', PORT);
});
httpsServer.listen(SSLPORT, function() {
console.log('HTTPS Server is running on: https://localhost:%s', SSLPORT);
});
// Welcome
app.get('/', function(req, res) {
if(req.protocol === 'https') {
res.status(200).send('Welcome to Safety Land!');
}
else {
res.status(200).send('Welcome!');
}
});
6. 运用HTTPS
向其他网站要求数据
- 在
HTTPS
模块中,能够运用request
要领向其他运用HTTPS
协定的网站要求数据
let req = https.request(options, callback(res){})
options
为一个对象或字符串,用于指定要求的目的的URL
地点,假如该参数值为一个字符串,将自动运用URL
模块中的parse
要领转换为一个对象.在options
参数值对象或运用parse
要领转换后对象中,能够指定的属性及属性值以下所示-
host
: 用于指定域名或目的主机的IP
地点,默许属性为localhost
-
hostname
: 用于指定域名或目的主机的IP
地点,默许属性为localhost
, 假如hostname
属性值与host
属性值都被指定,优先运用hostname属性值 -
port
: 指定目的服务器用于HTTP
客户单衔接的端口号,默许为443
-
method
: 用于指定HTTP
要求体式格局,默许为GET
-
path
: 用于指定要求途径及查询字符串,默许为/
-
headers
: 用于指定客户端要求头对象 -
auth
: 用于指定认证信息部份,比方user:password
- `agent: 用于指定用户代办
-
当在
options
参数值对象中运用以下所示的属性及属性值时,不能运用全局https.Agent
对象-
pfx
: 属性值为一个字符串或一个Buffer
对象,用于指定从pfx
文件读掏出的私钥,公钥及证书,运用该属性值不须要指定key
属性值,cert
属性值以及ca
属性值. -
key
: 属性值为一个字符串或一个Buffer
对象,用于指定从后缀名为pem
的私钥文件中读掏出来的私钥,该属性值为必需指定属性值,除非指定了pfx属性值 -
passphrase
: 属性值为一个字符串,用于为私钥文件或pfx
文件指定暗码 -
cert
: 属性值为一个字符串或一个Buffer
对象,用于指定从后缀名为pem
的文件中读物出来的公钥,该属性值为必需指定属性值,除非指定了pfx属性值 -
ca
: 属性值为一个字符串或一个Buffer
对象数组,用于指定一组证书,默许属性值为几个有名的证书受权认证中间,比方VerlSign
-
crl
: 属性值为一个字符串或一个Buffer
对象数组,用于指定证书撤消列表 -
ciphers
: 属性值为一个字符串值,用于形貌须要运用或作废运用的暗码.为了阻挠BEAST
进击,引荐奖ciphers
属性与honorCipherOrder
属性连系运用,以指定非CBC(Cipher-block chaining,暗码分组链接)
形式的暗码优先级,默许属性值为AES128-GCM-SHA256: RC4: HIGH: !MD5: !aNULL: !EDH
-
rejectUnauthorized
:属性值为一个布尔值,假如属性值为true
,那末服务器在客户端竖立衔接后,返回相应前起首考证客户端提交的证书,假如考证失利,触发客户端要求对象的error
事宜.
-
7. 竖立HTTPS
客户端
const https = require('https');
let options = {
hostname: 'github.com',
port: 443,
path: '/',
method: 'GET',
agent: false
}
let req = https.get(options, (res) => {
console.log('状况码:' + res.statusCode);
console.log('相应头:' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log('相应内容:' + chunk);
});
});
req.setTimeout(1000, (res) => {
res.abort();
});
req.on('error', (err) => {
if (err.code === 'ECONNRESET') {
console.log('socket端口超时');
} else {
console.log('在要求数据过程当中发作毛病,毛病代码为:' + err.code)
}
});
/**
* 状况码:200
* 相应头:{
"date": "Sun, 25 Feb 2018 14:24:24 GMT",
"content-type": "text/html; charset=utf-8",
"transfer-encoding": "chunked",
"connection": "close",
"server": "GitHub.com",
"status": "200 OK",
"cache-control": "no-cache",
"vary": "X-PJAX, Accept-Encoding",
"x-ua-compatible": "IE=Edge,chrome=1",
"set-cookie": ["logged_in=no; domain=.github.com; path=/; expires=Thu, 25 Feb 2038 14:24:24 -0000; secure; HttpOnly", "_gh_sess=eyJzZXNzaW9uX2lkIjoiMDY1YjM2ZmU4ZGM5MTFlZTliNjllMDI5ZDg0YzQ0ODUiLCJsYXN0X3JlYWRfZnJvbV9yZXBsaWNhcyI6MTUxOTU2ODY2NDUzMywiX2NzcmZfdG9rZW4iOiJ1ck5qWmZTMkpkeGpxMlN2ZzJhbklJM2pvaTJMVWEzWHcvSXEvTGtzVzBrPSJ9--8b5c0c203b3767a35f046b5ea4e375715e4d95be; path=/; secure; HttpOnly"],
"x-request-id": "1faefb3e691e8adc7e1a7d727c07236f",
"x-runtime": "0.050658",
"expect-ct": "max-age=2592000, report-uri=\"https://api.github.com/_private/browser/errors\"",
"content-security-policy": "default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; manifest-src 'self'; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com; worker-src 'self'",
"strict-transport-security": "max-age=31536000; includeSubdomains; preload",
"x-content-type-options": "nosniff",
"x-frame-options": "deny",
"x-xss-protection": "1; mode=block",
"x-runtime-rack": "0.058378",
"x-github-request-id": "1B82:60FF:117094:18A2C0:5A92C717"
}
*
****/