Node.JS、Socket.IO 的 SSL/TLS 双向认证笔记
2015-12-18 13:02
1511 查看
Node.JS、Socket.IO 的 SSL/TLS 双向认证笔记
node.js 天然就支持 SSL/TLS(除非是你自己编译的时候把 openssl 给剔除了),但是,如果你希望用客户端数字证书登录,则须配置成双向认证的方式,并要在服务端取得客户端证书的具体信息(如将证书的subject与用户身份进行绑定),文档未细述且无范例可参考。
废话少说,看代码:
C:\nodejs\test\https\testHttps.js
var https = require('https'), fs = require('fs'), util = require('util');
var sslopts = {
pfx: fs.readFileSync('svrCert.p12'),
passphrase: 'You,1SB!',
requestCert: true,
rejectUnauthorized: true
};
var server = https.createServer(sslopts, function (req, res) {
var usrcert = req.connection.getPeerCertificate(false);
res.writeHead(200);
res.end('<xmp>User Cert: ' + util.inspect(usrcert) + '</xmp>');
});
server.listen(4430, function() {
console.log('--------server bound to 4430');
});
如果你曾经在其他服务器上配置过双向 SSL,是不是觉得这也很简单?
那么,node.js 的好伙伴 socket.io 又如何呢?
从理论上说,node.js 是底层,SSL/TLS 和 socket.io 没啥关系,问题是在 socket.io 代码里又该如何读取客户端证书呢?
首先,如果你的 socket.io 版本是 0.9.x 或者更老,需要先修改一下这个文件:
C:\nodejs\node_modules\socket.io\lib\manager.js
打开它,找到类似下面的代码,只要小小的修改即可:
Manager.prototype.handshakeData = function (data) {
var connection = data.request.connection
, connectionAddress
, date = new Date;
if (connection.remoteAddress) {
connectionAddress = {
address: connection.remoteAddress
, port: connection.remotePort
};
} else if (connection.socket && connection.socket.remoteAddress) {
connectionAddress = {
address: connection.socket.remoteAddress
, port: connection.socket.remotePort
};
}
return {
headers: data.headers
, address: connectionAddress
, time: date.toString()
, query: data.query
, url: data.request.url
, xdomain: !!data.request.headers.origin
, secure: (!!connection.secure)||(!!connection.encrypted)
, connection: connection
, issued: +date
};
}
好,看看在 socket.io 里是怎么读取客户端证书的:
C:\nodejs\test\sktio_tls\app.js
var express = require('express'), https = require('https'), fs = require('fs');
var sslopts = {
pfx: fs.readFileSync('svrCert.p12'),
passphrase: 'You,1SB!',
requestCert: true,
rejectUnauthorized: true};
var app = express(), server = https.createServer(sslopts, app);
var io = require('socket.io', { rememberTransport: false, transports: ['WebSocket'] }).listen(server, { log: false } );
app.set('port', 4430);
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
//Socket.IO 0.9
io.sockets.on('connection', function(client) {
var handshake = client.handshake;
if (handshake.secure && handshake.connection.authorized) {
var cert = handshake.connection.getPeerCertificate();
client.emit('user', { name: cert.subject.CN, sid: client.id });
console.dir(cert);
}
//TODO ....
}
//Socket.IO 1.x
/*
io.sockets.on('connection', function(client) {
if (client.handshake.secure && client.conn.authorized) {
console.dir(client.conn.getPeerCertificate(false).subject);
}
//TODO ....
}
*/
server.listen(app.get('port'), function(){
console.log('--------------------start listening on port ' + app.get('port'));
});
双向认证总该在客户端做点什么吧?是的,如果客户端是浏览器就没什么可说的了,直接安装完证书即可;如果是 java 或者 Android,常用的 socket.io 支持库(叫什么来着?)里有个静态方法是用来配置 SSL 的:
io.socket.SocketIO.setDefaultSSLSocketFactory(SSLContext sslContext),熟悉 java 的 SSL 编程的你,还需要我多说吗?
node.js 天然就支持 SSL/TLS(除非是你自己编译的时候把 openssl 给剔除了),但是,如果你希望用客户端数字证书登录,则须配置成双向认证的方式,并要在服务端取得客户端证书的具体信息(如将证书的subject与用户身份进行绑定),文档未细述且无范例可参考。
废话少说,看代码:
C:\nodejs\test\https\testHttps.js
var https = require('https'), fs = require('fs'), util = require('util');
var sslopts = {
pfx: fs.readFileSync('svrCert.p12'),
passphrase: 'You,1SB!',
requestCert: true,
rejectUnauthorized: true
};
var server = https.createServer(sslopts, function (req, res) {
var usrcert = req.connection.getPeerCertificate(false);
res.writeHead(200);
res.end('<xmp>User Cert: ' + util.inspect(usrcert) + '</xmp>');
});
server.listen(4430, function() {
console.log('--------server bound to 4430');
});
如果你曾经在其他服务器上配置过双向 SSL,是不是觉得这也很简单?
那么,node.js 的好伙伴 socket.io 又如何呢?
从理论上说,node.js 是底层,SSL/TLS 和 socket.io 没啥关系,问题是在 socket.io 代码里又该如何读取客户端证书呢?
首先,如果你的 socket.io 版本是 0.9.x 或者更老,需要先修改一下这个文件:
C:\nodejs\node_modules\socket.io\lib\manager.js
打开它,找到类似下面的代码,只要小小的修改即可:
Manager.prototype.handshakeData = function (data) {
var connection = data.request.connection
, connectionAddress
, date = new Date;
if (connection.remoteAddress) {
connectionAddress = {
address: connection.remoteAddress
, port: connection.remotePort
};
} else if (connection.socket && connection.socket.remoteAddress) {
connectionAddress = {
address: connection.socket.remoteAddress
, port: connection.socket.remotePort
};
}
return {
headers: data.headers
, address: connectionAddress
, time: date.toString()
, query: data.query
, url: data.request.url
, xdomain: !!data.request.headers.origin
, secure: (!!connection.secure)||(!!connection.encrypted)
, connection: connection
, issued: +date
};
}
好,看看在 socket.io 里是怎么读取客户端证书的:
C:\nodejs\test\sktio_tls\app.js
var express = require('express'), https = require('https'), fs = require('fs');
var sslopts = {
pfx: fs.readFileSync('svrCert.p12'),
passphrase: 'You,1SB!',
requestCert: true,
rejectUnauthorized: true};
var app = express(), server = https.createServer(sslopts, app);
var io = require('socket.io', { rememberTransport: false, transports: ['WebSocket'] }).listen(server, { log: false } );
app.set('port', 4430);
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
//Socket.IO 0.9
io.sockets.on('connection', function(client) {
var handshake = client.handshake;
if (handshake.secure && handshake.connection.authorized) {
var cert = handshake.connection.getPeerCertificate();
client.emit('user', { name: cert.subject.CN, sid: client.id });
console.dir(cert);
}
//TODO ....
}
//Socket.IO 1.x
/*
io.sockets.on('connection', function(client) {
if (client.handshake.secure && client.conn.authorized) {
console.dir(client.conn.getPeerCertificate(false).subject);
}
//TODO ....
}
*/
server.listen(app.get('port'), function(){
console.log('--------------------start listening on port ' + app.get('port'));
});
双向认证总该在客户端做点什么吧?是的,如果客户端是浏览器就没什么可说的了,直接安装完证书即可;如果是 java 或者 Android,常用的 socket.io 支持库(叫什么来着?)里有个静态方法是用来配置 SSL 的:
io.socket.SocketIO.setDefaultSSLSocketFactory(SSLContext sslContext),熟悉 java 的 SSL 编程的你,还需要我多说吗?
相关文章推荐
- LeetCode 19:Remove Nth Node From End of List
- 遍历DOM(NodeIterator和TreeWalker的使用)(转)
- nodejs基础 -- 全局对象
- NodeJs+Eclipse环境配置
- nodejs编译安装
- nodejs基础 -- 路由
- 【Nodejs】windows下node.js安装教程图文详解
- 如何在不影响hadoop集群正常运行的情况下迁移主控节点[namenode]
- 使用 AngularJS & NodeJS 实现基于token 的认证应用(转)
- LeetCode OJ:Reverse Nodes in k-Group(K个K个的分割节点)
- leetcode19---Remove Nth Node From End of List
- (java)Remove Nth Node From End of List
- nodejs webstorm
- Hadoop的datanode,namenode无法启动
- 用Node完成AWS S3的Upload流程之全世界最简版
- NODEJS 初学示例
- 117 Populating Next Right Pointers in Each Node II
- Node.js 的Web server--Fenix
- Nodejs源码分析之assert
- Populating Next Right Pointers in Each Node,Populating Next Right Pointers in Each Node II