UNPKG

shark-node-openid

Version:

shark-node-openid is used for netease's openid.

258 lines (237 loc) 10.6 kB
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 };