您的位置:首页 > Web前端 > Node.js

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 编程的你,还需要我多说吗?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: