shark-node-openid
Version:
shark-node-openid is used for netease's openid.
258 lines (237 loc) • 10.6 kB
JavaScript
var q = require('q');
var OpenIdLoginService = require('../service/OpenIdLoginService');
var OpenIdLoginUserModel = require('../model/OpenIdLoginUserModel');
var log4js = require('log4js');
var logger = log4js.getLogger('shark_openid');
function isLogin(session){
var defer = q.defer();
if(session.openid === void 0 || session.openid.email === void 0){
defer.reject();
}else{
/* 此处需要判断过期时间 */
OpenIdLoginService.UserExipreTime(session.openid.email).then(function(){
defer.resolve({
"login": true
});
}, function(){
defer.reject({
"login": false
});
});
}
return defer.promise;
}
function to_openid_login(session, reqHost, reqPath, protocol, contextPath){
//向openId服务器发送post请求
var querystring = require('querystring');
var https = require('https');
var defer = q.defer();
var post_data = {
"openid.mode":"associate",
"openid.assoc_type":"HMAC-SHA256",
"openid.session_type":"no-encryption"
};
post_data = querystring.stringify(post_data);
var contentLen = Buffer.byteLength(post_data, 'utf8');
var post_options = {
host: 'login.netease.com',
path: '/openid/',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': contentLen
}
};
var REDIRECT_URL = "";
var post_req = https.request(post_options, function(httpRes) {
var buffers = [];
httpRes.on('data', function(chunk) {
buffers.push(chunk);
});
httpRes.on('end', function(chunk) {
var wholeData = Buffer.concat(buffers);
var dataStr = wholeData.toString('utf8');
var items = dataStr.split('\n');
var results = {};
session['ASSOC'] = {};
for(var index = 0;index < items.length;index++){
var key_values = items[index].split(':');
if(key_values.length === 2){
results[key_values[0]] = key_values[1];
session['ASSOC'][key_values[0]] = key_values[1];
}else if(key_values.length !== 1){
results[key_values[0]] = items[index].substring(key_values.length);
session['ASSOC'][key_values[0]] = items[index].substring(key_values.length);
}
}
logger.info("openid will express in " + session['ASSOC']['expires_in'] + " second");
session['ASSOC']['expires_in'] = parseInt(parseInt(session['ASSOC']['expires_in'])*1000 + Date.parse( new Date()));
var host_addr = protocol + reqHost;
session.last_url = protocol + reqHost + reqPath;
var path = 'https://login.netease.com/openid/?';
var queryParams = ['openid.ns=' + 'http://specs.openid.net/auth/2.0',
'openid.mode=' + 'checkid_setup',
'openid.assoc_handle=' + session['ASSOC']['assoc_handle'],
'openid.return_to=' + host_addr + contextPath + '/openid_login/',
'openid.claimed_id=' + 'http://specs.openid.net/auth/2.0/identifier_select',
'openid.identity=' + 'http://specs.openid.net/auth/2.0/identifier_select',
'openid.realm=' + host_addr,
'openid.ns.sreg=' + 'http://openid.net/extensions/sreg/1.1',
'openid.sreg.required=' + "nickname,email,fullname"
];
var query = queryParams.join('&');
// 如果要获取部门信息,需要申请权限
// "openid.ns.ax=" + "http://openid.net/srv/ax/1.0",
// "openid.ax.mode=" + "fetch_request",
// "openid.ax.type.empno=" + "https://login.netease.com/openid/empno/",
// "openid.ax.type.dep=" + "https://login.netease.com/openid/dep/",
// "openid.ax.required=" + "empno,dep"
/* 实际应用中,需要交由浏览器进行Redirect的URL,用户在这里完成交互认证 */
REDIRECT_URL = path + query;
defer.resolve(REDIRECT_URL);
});
});
post_req.write(post_data);
post_req.end();
post_req.on('error', function(e){
logger.info("==============");
logger.info(e);
defer.reject({
"code": 201,
"message": "fail to connect to openid server"
});
});
return defer.promise;
}
function checkOpenIdCallBack(urlParams, session){
var defer = q.defer();
do{
/* 网页上面第三步骤中的第一步 */
/* 入参检查 */
if((urlParams['openid.mode'] !== 'id_res') || (urlParams['openid.identity'].indexOf("https://login.netease.com/openid/") !== 0) ||
(urlParams['openid.claimed_id'].indexOf("https://login.netease.com/openid/") !== 0) || (session['ASSOC'] === void 0)){
logger.info("========");
logger.info("openid.mode" + ":" + urlParams['openid.mode']);
logger.info("openid.mode" + ":" + urlParams['openid.identity']);
logger.info("openid.mode" + ":" + urlParams['openid.claimed_id']);
logger.info("ASSOC:%o" , session['ASSOC']);
logger.info("Here I am!");
defer.reject({
"code": 201,
"message": "非法入参",
"redirect": session.last_url
});
break;
}
/* 网页上面第三步骤中的第二步 */
if(urlParams['openid.assoc_handle'] !== session['ASSOC']['assoc_handle']){
// 可能consumer没有assoc或者OpenID Server不认可之前的association handle
// print u"assoc_handl不一致,进入 check_authentication流程"
/* 如果不一致,请直接看4.依赖OpenID Server的数据校验 */
logger.info("=====");
logger.info(session['ASSOC']);
logger.info('openid.assoc_handle:' + urlParams['openid.assoc_handle']);
logger.info("session assoc assoc_handle : " + session['ASSOC']['assoc_handle']);
logger.info("Here I am!");
defer.reject({
"code": 202,
"message": "验证出错,请重新登陆",
"redirect": session.last_url
});
break;
}
var SIGNED_CONTENT = "";
var openid_signed = urlParams['openid.signed'].split(',');
for(var i = 0; i < openid_signed.length; i++){
SIGNED_CONTENT += openid_signed[i] + ":" + urlParams['openid.' + openid_signed[i]] + "\n";
}
/* 验证签名值是否相等 */
if(require('crypto').createHmac('SHA256', new Buffer(session['ASSOC']['mac_key'], 'base64')).update(new Buffer(SIGNED_CONTENT)).digest('base64') !== urlParams['openid.sig']){
logger.info("==========");
logger.info("session assoc mac_key:" + session['ASSOC']['mac_key']);
logger.info('openid.sig:' + urlParams['openid.sig']);
logger.info("Here I am!");
defer.reject({
"code": 206,
"message": "签名值不正确",
"redirect": session.last_url
});
break;
}
session.openid = {};
session.openid.email = urlParams['openid.sreg.email'];
/* 此处需要判断过期时间 */
var openIdLoginUserModel = new OpenIdLoginUserModel();
openIdLoginUserModel.setUserEmail(urlParams['openid.sreg.email']);
openIdLoginUserModel.setExpiresTime(session['ASSOC']['expires_in']);
openIdLoginUserModel.setFullName(urlParams['openid.sreg.fullname']);
openIdLoginUserModel.setNickName(urlParams['openid.sreg.nickname']);
OpenIdLoginService.UserExipreTime(session.openid.email).then(function(data){
/* 正常更新 */
OpenIdLoginService.updateOpenIdUser(openIdLoginUserModel).then(function(){
defer.resolve({
"code": 200,
"redirect": session.last_url
});
}, function(result){
logger.info("==========");
logger.info(result);
logger.info("Here I am!");
defer.reject({
"code": 203,
"message": "保存数据库失败1",
"redirect": session.last_url
});
});
}, function(data){
/* 没有找到对应的用户 */
if(data.code === 201){
OpenIdLoginService.addOpenIdUser(openIdLoginUserModel).then(function(){
defer.resolve({
"code": 200,
"redirect": session.last_url
});
}, function(result){
logger.info("=============");
logger.info(result);
logger.info("Here I am!");
defer.reject({
"code": 204,
"message": "保存数据库失败3",
"redirect": session.last_url
});
});
}else if(data.code === 202){ /* 过期了 */
OpenIdLoginService.updateOpenIdUser(openIdLoginUserModel).then(function(){
defer.resolve({
"code": 200,
"redirect": session.last_url
});
}, function(result){
logger.info("=============");
logger.info(result);
logger.info("Here I am!");
defer.reject({
"code": 205,
"message": "保存数据库失败2",
"redirect": session.last_url
});
});
}else {
logger.info("=============");
logger.info("Here I am!");
defer.reject({
"code": 206,
"message": "参数不正确",
"redirect": session.last_url
});
}
});
}while(0);
return defer.promise;
}
module.exports = {
isLogin: isLogin,
to_openid_login: to_openid_login,
checkOpenIdCallBack: checkOpenIdCallBack
};