Authored by 毕凯

Merge branch 'hotfix/login' into 'master'

Hotfix/login



See merge request !454
@@ -31,4 +31,4 @@ exports.sidebar = function(req, res, next) { @@ -31,4 +31,4 @@ exports.sidebar = function(req, res, next) {
31 layout: false 31 layout: false
32 }); 32 });
33 }).catch(next); 33 }).catch(next);
34 -}  
  34 +};
@@ -81,7 +81,9 @@ const common = { @@ -81,7 +81,9 @@ const common = {
81 let passLogin = _.get(req, 'cookies._WX_PASS_LOGIN', false); 81 let passLogin = _.get(req, 'cookies._WX_PASS_LOGIN', false);
82 82
83 if (req.yoho.isWechat && !passLogin) { 83 if (req.yoho.isWechat && !passLogin) {
84 - return res.redirect('/passport/login/wechat'); 84 + return res.redirect(helpers.urlFormat('/passport/login/wechat', {
  85 + refer: req.query.refer || req.get('Referer') || '/'
  86 + }));
85 } 87 }
86 next(); 88 next();
87 }, 89 },
@@ -128,11 +130,13 @@ const local = { @@ -128,11 +130,13 @@ const local = {
128 // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie 130 // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie
129 // res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800); 131 // res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800);
130 132
  133 + // 170406 账户密码方式登录可以选择是否开启验证码,默认开关是关闭状态,此时开启验证码,开关开启,无需验证
  134 + let captchaShow = _.get(req.app.locals.wap, 'close.loginValidation', false);
131 135
132 res.render('login', { 136 res.render('login', {
133 width750: true, 137 width750: true,
134 loginIndex: true, // 模板中使用JS的标识 138 loginIndex: true, // 模板中使用JS的标识
135 - captchaShow: true, // 170306 因为暴力破解密码问题,要求每次都展示验证码 139 + captchaShow: !captchaShow, // 170306 因为暴力破解密码问题,要求每次都展示验证码
136 backUrl: 'javascript:history.go(-1)', // eslint-disable-line 140 backUrl: 'javascript:history.go(-1)', // eslint-disable-line
137 showHeaderImg: true, // 控制显示头部图片 141 showHeaderImg: true, // 控制显示头部图片
138 isPassportPage: true, // 模板中模块标识 142 isPassportPage: true, // 模板中模块标识
@@ -170,13 +174,14 @@ const local = { @@ -170,13 +174,14 @@ const local = {
170 // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie 174 // 设置登录有效时间30分钟, 防机器刷,cache不稳定,改为cookie
171 // res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800); 175 // res.cookie('LE' + md5('_LOGIN_EXPIRE'), (new Date()).getTime() / 1000 + 1800);
172 176
173 - 177 + // 170406 账户密码方式登录可以选择是否开启验证码,默认开关是关闭状态,此时开启验证码,开关开启,无需验证
  178 + let captchaShow = _.get(req.app.locals.wap, 'close.loginValidation', false);
174 179
175 res.render('international', { 180 res.render('international', {
176 width750: true, 181 width750: true,
177 backUrl: 'javascript:history.go(-1)', // eslint-disable-line 182 backUrl: 'javascript:history.go(-1)', // eslint-disable-line
178 loginInternational: true, // 模板中使用JS的标识 183 loginInternational: true, // 模板中使用JS的标识
179 - captchaShow: true, // 170306 因为暴力破解密码问题,要求每次都展示验证码 184 + captchaShow: !captchaShow, // 170306 因为暴力破解密码问题,要求每次都展示验证码
180 isPassportPage: true, // 模板中模块标识 185 isPassportPage: true, // 模板中模块标识
181 headerText: '登录', 186 headerText: '登录',
182 areaCode: '+86', // 默认区号 187 areaCode: '+86', // 默认区号
@@ -250,6 +255,18 @@ const local = { @@ -250,6 +255,18 @@ const local = {
250 255
251 const wechat = { 256 const wechat = {
252 login: (req, res, next) => { 257 login: (req, res, next) => {
  258 + // 微信里边已经登录的时候,不再跳转登录
  259 + if (req.user.uid) {
  260 + let refer = req.query.refer || decodeURI(req.cookies.refer) || config.siteUrl;
  261 +
  262 + if (/sign|login/.test(refer)) {
  263 + refer = `${config.siteUrl}/home`;
  264 + }
  265 +
  266 + refer = utils.refererLimit(refer);
  267 + return res.redirect(refer);
  268 + }
  269 +
253 // 设置为原链接标识originalUrl 270 // 设置为原链接标识originalUrl
254 req.session.originalUrl = 'true'; 271 req.session.originalUrl = 'true';
255 req.session.authState = uuid.v4(); 272 req.session.authState = uuid.v4();
@@ -20,6 +20,11 @@ const check = (req, res, next) => { @@ -20,6 +20,11 @@ const check = (req, res, next) => {
20 return next(); 20 return next();
21 } 21 }
22 22
  23 + // 170406 采用账号密码方式登录验证码可以配置关闭,默认开关是关闭状态,这时需要验证,开关开启,无需验证
  24 + if (_.get(req.app.locals.wap, 'close.loginValidation', false) && req.path === '/passport/login/auth') {
  25 + return next();
  26 + }
  27 +
23 // 使用极验证 28 // 使用极验证
24 let useGeetest = !_.get(req.app.locals.wap, 'geetest.validation', false); 29 let useGeetest = !_.get(req.app.locals.wap, 'geetest.validation', false);
25 30
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 const _ = require('lodash'); 2 const _ = require('lodash');
3 const aes = require('./aes-pwd'); 3 const aes = require('./aes-pwd');
4 const authcode = require('../../../utils/authcode'); 4 const authcode = require('../../../utils/authcode');
  5 +const logger = global.yoho.logger;
5 const sign = global.yoho.sign; 6 const sign = global.yoho.sign;
6 const api = global.yoho.API; 7 const api = global.yoho.API;
7 const uuid = require('uuid'); 8 const uuid = require('uuid');
@@ -35,10 +36,13 @@ class Auth { @@ -35,10 +36,13 @@ class Auth {
35 param.shopping_key = shoppingKey; 36 param.shopping_key = shoppingKey;
36 } 37 }
37 38
  39 + logger.info(`${profile}, login from ${ip}`);
  40 +
38 return api.post('', param, { 41 return api.post('', param, {
39 headers: { 42 headers: {
40 'user-agent': 'yoho/nodejs', 43 'user-agent': 'yoho/nodejs',
41 - 'X-YOHO-IP': ip 44 + 'X-YOHO-IP': ip,
  45 + 'X-Forwarded-For': ip
42 } 46 }
43 }); 47 });
44 } 48 }
@@ -27,7 +27,7 @@ const router = express.Router(); // eslint-disable-line @@ -27,7 +27,7 @@ const router = express.Router(); // eslint-disable-line
27 router.get('/passport/geetest/register', geetest.register); 27 router.get('/passport/geetest/register', geetest.register);
28 28
29 // 兼容老的路由 29 // 兼容老的路由
30 -router.get('/signin.html', validateCode.load, login.common.weixinCheck, 30 +router.get('/signin.html', login.common.weixinCheck, validateCode.load,
31 login.common.beforeLogin, login.common.clearCookie, smsLogin.loginPage); 31 login.common.beforeLogin, login.common.clearCookie, smsLogin.loginPage);
32 router.get('/reg.html', validateCode.load, disableBFCahce, reg.index); 32 router.get('/reg.html', validateCode.load, disableBFCahce, reg.index);
33 router.get('/login.html', validateCode.load, 33 router.get('/login.html', validateCode.load,
@@ -78,10 +78,6 @@ router.get('/passport/login/qq/callback', login.qq.callback); @@ -78,10 +78,6 @@ router.get('/passport/login/qq/callback', login.qq.callback);
78 router.get('/passport/login/alipay', login.common.beforeLogin, login.alipay.login); 78 router.get('/passport/login/alipay', login.common.beforeLogin, login.alipay.login);
79 router.get('/passport/login/alipay/callback', login.alipay.callback); 79 router.get('/passport/login/alipay/callback', login.alipay.callback);
80 80
81 -// alipay登录  
82 -router.get('/login/alipay', login.common.beforeLogin, login.alipay.login);  
83 -router.get('/login/alipay/callback', login.alipay.callback);  
84 -  
85 // 登录绑定 81 // 登录绑定
86 router.get('/passport/bind/index', validateCode.load, bind.indexPage); 82 router.get('/passport/bind/index', validateCode.load, bind.indexPage);
87 router.post('/passport/bind/bindCheck', validateCode.check, bind.bindCheck); 83 router.post('/passport/bind/bindCheck', validateCode.check, bind.bindCheck);
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 <input id="pwd" class="pwd input" type="password" placeholder="密码"> 10 <input id="pwd" class="pwd input" type="password" placeholder="密码">
11 </div> 11 </div>
12 {{!--图片验证--}} 12 {{!--图片验证--}}
13 - <div data-geetest="{{useGeetest}}" id="js-img-check"></div> 13 + <div data-userverify="{{captchaShow}}" data-geetest="{{useGeetest}}" id="js-img-check"></div>
14 14
15 <span id="btn-login" class="btn btn-login disble row">登录</span> 15 <span id="btn-login" class="btn btn-login disble row">登录</span>
16 </div> 16 </div>
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 <input id="pwd" class="pwd input" type="password" placeholder="密码"> 9 <input id="pwd" class="pwd input" type="password" placeholder="密码">
10 </div> 10 </div>
11 {{!--图片验证--}} 11 {{!--图片验证--}}
12 - <div data-geetest="{{useGeetest}}" id="js-img-check"></div> 12 + <div data-userverify="{{captchaShow}}" data-geetest="{{useGeetest}}" id="js-img-check"></div>
13 <span id="btn-login" class="btn btn-login disable">登录</span> 13 <span id="btn-login" class="btn btn-login disable">登录</span>
14 <p class="op-container"> 14 <p class="op-container">
15 <a class="op-item internat" href={{internationalUrl}}>海外手机</a> 15 <a class="op-item internat" href={{internationalUrl}}>海外手机</a>
@@ -22,7 +22,7 @@ module.exports = (req, res, next) => { @@ -22,7 +22,7 @@ module.exports = (req, res, next) => {
22 return next(); 22 return next();
23 } 23 }
24 24
25 - if (res.statusCode == 403) { 25 + if (_.toNumber(res.statusCode) === 403) {
26 return res.end(); 26 return res.end();
27 } 27 }
28 28
@@ -21,7 +21,11 @@ const _getClientIp = req => { @@ -21,7 +21,11 @@ const _getClientIp = req => {
21 remoteIp = _.trim(arr[arr.length - 1]); 21 remoteIp = _.trim(arr[arr.length - 1]);
22 } 22 }
23 23
24 - return remoteIp; 24 + if (_.startsWith(remoteIp, '10.66.')) {
  25 + remoteIp = req.get('X-Real-IP');
  26 + }
  27 +
  28 + return _.trim(remoteIp);
25 }; 29 };
26 30
27 module.exports = () => { 31 module.exports = () => {
1 { 1 {
2 "name": "m-yohobuy-node", 2 "name": "m-yohobuy-node",
3 - "version": "5.5.11", 3 + "version": "5.5.12",
4 "private": true, 4 "private": true,
5 "description": "A New Yohobuy Project With Express", 5 "description": "A New Yohobuy Project With Express",
6 "repository": { 6 "repository": {
@@ -13,6 +13,7 @@ let $phoneNum = $('#phone-num'), @@ -13,6 +13,7 @@ let $phoneNum = $('#phone-num'),
13 $loginBtn = $('#btn-login'), 13 $loginBtn = $('#btn-login'),
14 14
15 $captcha = $('#js-img-check'), 15 $captcha = $('#js-img-check'),
  16 + useVerify = $captcha.data('userverify'), // 170406 是否使用验证
16 17
17 pnPass = false, 18 pnPass = false,
18 pwdPass = false; 19 pwdPass = false;
@@ -23,15 +24,18 @@ let tip = require('plugin/tip'); @@ -23,15 +24,18 @@ let tip = require('plugin/tip');
23 let trim = $.trim; 24 let trim = $.trim;
24 let showErrTip = tip.show; 25 let showErrTip = tip.show;
25 26
26 -let validate = new Validate($captcha, {  
27 - useREM: {  
28 - rootFontSize: 40,  
29 - picWidth: 150  
30 - }  
31 -}); 27 +let validate = {};
32 28
33 -validate.init(); 29 +if (useVerify) {
  30 + validate = new Validate($captcha, {
  31 + useREM: {
  32 + rootFontSize: 40,
  33 + picWidth: 150
  34 + }
  35 + });
34 36
  37 + validate.init();
  38 +}
35 39
36 // 登录按钮状态切换 40 // 登录按钮状态切换
37 function switchLoginBtnStatus() { 41 function switchLoginBtnStatus() {
@@ -45,6 +49,47 @@ function resetForm() { @@ -45,6 +49,47 @@ function resetForm() {
45 $loginBtn.text('登录').addClass('disable'); 49 $loginBtn.text('登录').addClass('disable');
46 } 50 }
47 51
  52 +/**
  53 + * 登录校验
  54 + */
  55 +function loginAuth(params) {
  56 + $.ajax({
  57 + type: 'POST',
  58 + url: '/passport/login/auth',
  59 + data: params,
  60 + success: function(data) {
  61 + let res;
  62 +
  63 + validate && validate.type === 2 && validate.refresh();
  64 + if (data.code === 200) {
  65 + res = data.data;
  66 + showErrTip('登录成功');
  67 +
  68 + // 3秒后强制跳转
  69 + setTimeout(() => {
  70 + location.href = res.href;
  71 + }, 1500);
  72 +
  73 + $loginBtn.text('登录成功');
  74 + showErrTip('登录成功');
  75 + } else {
  76 + if (useVerify && data.captchaShow) {
  77 + ((data.changeCaptcha && validate.type !== 2) && validate.refresh());
  78 + }
  79 +
  80 + showErrTip(data.message);
  81 + resetForm();
  82 + }
  83 + },
  84 + error: function() {
  85 + showErrTip('网络断开连接啦~');
  86 + $loginBtn.text('登录');
  87 +
  88 + validate && validate.refresh();
  89 + }
  90 + });
  91 +}
  92 +
48 // Android-UC下显示select的direction:rtl无效的临时解决办法 93 // Android-UC下显示select的direction:rtl无效的临时解决办法
49 api.selectCssHack($countrySelect); 94 api.selectCssHack($countrySelect);
50 95
@@ -90,52 +135,21 @@ $loginBtn.on('touchstart', function() { @@ -90,52 +135,21 @@ $loginBtn.on('touchstart', function() {
90 } 135 }
91 136
92 if ((api.phoneRegx[areaCode].test(pn) || areaCode !== '+86') && api.pwdValidate(pwd)) { 137 if ((api.phoneRegx[areaCode].test(pn) || areaCode !== '+86') && api.pwdValidate(pwd)) {
93 - validate.getResults().then((result) => {  
94 - $loginBtn.text('正在登录...').addClass('disable');  
95 - let params = {  
96 - areaCode: areaCode.replace('+', ''),  
97 - account: pn,  
98 - password: pwd  
99 - };  
100 -  
101 - $.extend(params, result);  
102 -  
103 - $.ajax({  
104 - type: 'POST',  
105 - url: '/passport/login/auth',  
106 - data: params,  
107 - success: function(data) {  
108 - let res;  
109 -  
110 - validate.type === 2 && validate.refresh();  
111 - if (data.code === 200) {  
112 - res = data.data;  
113 - showErrTip('登录成功');  
114 -  
115 - // 3秒后强制跳转  
116 - setTimeout(() => {  
117 - location.href = res.href;  
118 - }, 1500);  
119 -  
120 - $loginBtn.text('登录成功');  
121 - showErrTip('登录成功');  
122 - } else {  
123 - if (data.captchaShow) {  
124 - ((data.changeCaptcha && validate.type !== 2) && validate.refresh());  
125 - }  
126 -  
127 - showErrTip(data.message);  
128 - resetForm();  
129 - }  
130 - },  
131 - error: function() {  
132 - showErrTip('网络断开连接啦~');  
133 - $loginBtn.text('登录');  
134 -  
135 - validate.refresh();  
136 - } 138 + let params = {
  139 + areaCode: areaCode.replace('+', ''),
  140 + account: pn,
  141 + password: pwd
  142 + };
  143 +
  144 + if (useVerify) {
  145 + validate.getResults().then((result) => {
  146 + $loginBtn.text('正在登录...').addClass('disable');
  147 + $.extend(params, result);
  148 + loginAuth(params);
137 }); 149 });
138 - }); 150 + } else {
  151 + loginAuth(params);
  152 + }
139 } else { 153 } else {
140 showErrTip('账号或密码有错误,请重新输入'); 154 showErrTip('账号或密码有错误,请重新输入');
141 $loginBtn.text('登录').addClass('disable'); 155 $loginBtn.text('登录').addClass('disable');
@@ -14,6 +14,7 @@ let $account = $('#account'), @@ -14,6 +14,7 @@ let $account = $('#account'),
14 $ways = $('#retrive-pwd-ways'), 14 $ways = $('#retrive-pwd-ways'),
15 15
16 $captcha = $('#js-img-check'), 16 $captcha = $('#js-img-check'),
  17 + useVerify = $captcha.data('userverify'), // 170406 是否使用验证
17 18
18 accPass = false, 19 accPass = false,
19 pwdPass = false; 20 pwdPass = false;
@@ -25,14 +26,18 @@ let trim = $.trim; @@ -25,14 +26,18 @@ let trim = $.trim;
25 let showErrTip = tip.show; 26 let showErrTip = tip.show;
26 27
27 28
28 -let validate = new Validate($captcha, {  
29 - useREM: {  
30 - rootFontSize: 40,  
31 - picWidth: 150  
32 - }  
33 -}); 29 +let validate = {};
  30 +
  31 +if (useVerify) {
  32 + validate = new Validate($captcha, {
  33 + useREM: {
  34 + rootFontSize: 40,
  35 + picWidth: 150
  36 + }
  37 + });
34 38
35 -validate.init(); 39 + validate.init();
  40 +}
36 41
37 // 登录按钮状态切换 42 // 登录按钮状态切换
38 function switchLoginBtnStatus() { 43 function switchLoginBtnStatus() {
@@ -60,6 +65,62 @@ function hideRetrivePanel() { @@ -60,6 +65,62 @@ function hideRetrivePanel() {
60 $ways.hide(); 65 $ways.hide();
61 } 66 }
62 67
  68 +/**
  69 + * 登录校验
  70 + */
  71 +function loginAuth(params, acc) {
  72 + $.ajax({
  73 + type: 'POST',
  74 + url: '/passport/login/auth',
  75 + data: params,
  76 + success: function(data) {
  77 + let res,
  78 + LOGI_TYPE;
  79 +
  80 + if (acc.indexOf('@') > 0) {
  81 + LOGI_TYPE = 8;
  82 + } else {
  83 + LOGI_TYPE = 5;
  84 + }
  85 +
  86 + if (window._yas && window._yas.sendCustomInfo) {
  87 + window._yas.sendCustomInfo({
  88 + op: 'YB_MY_LOGIN_C',
  89 + param: JSON.stringify({
  90 + C_ID: window._ChannelVary[window.cookie('_Channel')],
  91 + LOGI_TYPE: LOGI_TYPE
  92 + })
  93 + }, true);
  94 + }
  95 + validate && validate.type === 2 && validate.refresh();
  96 + if (data.code === 200) {
  97 + res = data.data;
  98 +
  99 + showErrTip('登录成功');
  100 + location.href = res.href;
  101 + $loginBtn.text('登录成功');
  102 + } else {
  103 + if (useVerify && data.captchaShow) {
  104 + ((data.changeCaptcha && validate.type !== 2) && validate.refresh());
  105 + }
  106 +
  107 + showErrTip(data.message);
  108 + resetForm();
  109 + }
  110 +
  111 + return data;
  112 + },
  113 + error: function() {
  114 + showErrTip('网络断开连接啦~');
  115 +
  116 + validate && validate.refresh();
  117 + },
  118 + complete: function() {
  119 + $loginBtn.text('登录').removeClass('disable');
  120 + }
  121 + });
  122 +}
  123 +
63 // 密码显示与隐藏 124 // 密码显示与隐藏
64 api.bindEyesEvt(); 125 api.bindEyesEvt();
65 126
@@ -95,67 +156,23 @@ $loginBtn.on('touchstart', function() { @@ -95,67 +156,23 @@ $loginBtn.on('touchstart', function() {
95 156
96 // 验证账号(数字或者邮箱)和密码合理性 157 // 验证账号(数字或者邮箱)和密码合理性
97 if ((/^[0-9]+$/.test(acc) || api.emailRegx.test(acc)) && api.pwdValidate(pwd)) { 158 if ((/^[0-9]+$/.test(acc) || api.emailRegx.test(acc)) && api.pwdValidate(pwd)) {
98 - validate.getResults().then((result) => {  
99 - $loginBtn.text('正在登录...').addClass('disable');  
100 -  
101 - let params = {  
102 - account: acc,  
103 - password: pwd  
104 - };  
105 -  
106 - $.extend(params, result);  
107 -  
108 - $.ajax({  
109 - type: 'POST',  
110 - url: '/passport/login/auth',  
111 - data: params,  
112 - success: function(data) {  
113 - let res,  
114 - LOGI_TYPE;  
115 -  
116 - if (acc.indexOf('@') > 0) {  
117 - LOGI_TYPE = 8;  
118 - } else {  
119 - LOGI_TYPE = 5;  
120 - }  
121 -  
122 - if (window._yas && window._yas.sendCustomInfo) {  
123 - window._yas.sendCustomInfo({  
124 - op: 'YB_MY_LOGIN_C',  
125 - param: JSON.stringify({  
126 - C_ID: window._ChannelVary[window.cookie('_Channel')],  
127 - LOGI_TYPE: LOGI_TYPE  
128 - })  
129 - }, true);  
130 - }  
131 - validate.type === 2 && validate.refresh();  
132 - if (data.code === 200) {  
133 - res = data.data;  
134 -  
135 - showErrTip('登录成功');  
136 - location.href = res.href;  
137 - $loginBtn.text('登录成功');  
138 - } else {  
139 - if (data.captchaShow) {  
140 - ((data.changeCaptcha && validate.type !== 2) && validate.refresh());  
141 - }  
142 -  
143 - showErrTip(data.message);  
144 - resetForm();  
145 - }  
146 -  
147 - return data;  
148 - },  
149 - error: function() {  
150 - showErrTip('网络断开连接啦~');  
151 -  
152 - validate.refresh();  
153 - },  
154 - complete: function() {  
155 - $loginBtn.text('登录').removeClass('disable');  
156 - }  
157 - });  
158 - }, () => {}); 159 + let params = {
  160 + account: acc,
  161 + password: pwd
  162 + };
  163 +
  164 + if (useVerify) {
  165 + validate.getResults().then((result) => {
  166 + $loginBtn.text('正在登录...').addClass('disable');
  167 +
  168 + $.extend(params, result);
  169 +
  170 + // auth
  171 + loginAuth(params, acc);
  172 + }, () => {});
  173 + } else {
  174 + loginAuth(params, acc);
  175 + }
159 } else { 176 } else {
160 showErrTip('账号或密码有错误,请重新输入'); 177 showErrTip('账号或密码有错误,请重新输入');
161 $loginBtn.text('登录').removeClass('disable'); 178 $loginBtn.text('登录').removeClass('disable');