Authored by 陈轩

登陆失败3次出现 滑动验证码

... ... @@ -9,6 +9,7 @@
const passport = require('passport');
// const md5 = require('md5');
const _ = require('lodash');
const uuid = require('uuid');
const cookie = global.yoho.cookie;
const helpers = global.yoho.helpers;
... ... @@ -97,6 +98,7 @@ const local = {
});
res.render('login', {
slideUnlock: _.get(req.session, 'login.errorCount') <= 0,
loginIndex: true, // 模板中使用JS的标识
// 返回的URL链接
... ... @@ -135,6 +137,8 @@ const local = {
});
res.render('international', {
slideUnlock: _.get(req.session, 'login.errorCount') <= 0,
// 返回的URL链接
backUrl: 'javascript:history.go(-1)', // eslint-disable-line
loginInternational: true, // 模板中使用JS的标识
... ... @@ -148,13 +152,27 @@ const local = {
});
},
login: (req, res, next) => {
let count = _.get(req.session, 'login.errorCount');
if (count == null) { //eslint-disable-line
_.set(req.session, 'login.errorCount', 3);
}
passport.authenticate('local', (err, user) => {
if (err) {
res.json({
let obj = {
code: 400,
message: err,
data: ''
});
};
--req.session.login.errorCount;
if (req.session.login.errorCount <= 0) {
obj.slideUnlock = true;
}
res.json(obj);
} else {
let refer = req.cookies.refer;
... ...
... ... @@ -9,6 +9,8 @@
<div class="input-container row has-eye">
<input id="pwd" class="pwd input" type="password" placeholder="密码">
</div>
<div id="js-slideunlock" data-init="{{slideUnlock}}"></div>
<span id="btn-login" class="btn btn-login disble row">登录</span>
</div>
</div>
\ No newline at end of file
... ...
... ... @@ -8,6 +8,7 @@
<div class="input-container row has-eye">
<input id="pwd" class="pwd input" type="password" placeholder="密码">
</div>
<div id="js-slideunlock" data-init="{{slideUnlock}}"></div>
<span id="btn-login" class="btn btn-login disable">登录</span>
<p class="op-container">
{{!--<a class="sms-login" href={{smsLoginUrl}}>手机号码快捷登录</a>--}}
... ...
No preview for this file type
... ... @@ -86,6 +86,8 @@
<glyph unicode="&#xe64b;" glyph-name="uniE64B" d="M379-128q-57 0-122 51.5t-97 132.5q-26 71-27 149.5t24 151.5q11 33 32.5 70.5t37 58.5 46.5 62q17 20 51 68l11 14 23 34q9 14 21 35t18.5 38.5 11.5 38 4 42.5-7 44q-6 11 7 24 7 7 20 7 149-50 216-284 27 50 58 69 12 6 23 0t11-21q-3-59 11.5-126.5t42.5-126.5q4-5 9-17t8-17q51-89 55-157 4-63-14.5-126.5t-65.5-120-115-80.5q-30-11-61-11-18 0-30.5 5t-18 12.5-7.5 13-2 10.5q0 7 2 13t4 10 7.5 9.5 7.5 7 9 6.5 8 6l3 3q36 26 54 75.5t7 95.5q-4 28-27 75-2 6-7.5 20t-8.5 22-6.5 20-4.5 23q0-2-2-5t-2-5q-15-42-20-75 0-45 7-58 7-5 7.5-14.5t-4.5-16.5q-5-8-14-10t-17 3v0q-67 44-85 120 7 34 7 78v45q0 68-10 92-14-53-28-72-22-39-37-58-6-6-15.5-20t-12.5-18q-13-22-24-46.5t-21.5-61.5-5.5-78 28-76q3-7 7.5-12.5t8-10 8.5-10 7.5-8 8-7 7.5-6.5 7.5-6.5 6.5-4.5q11-9 16.5-14.5t10-14.5 0.5-19q-5-18-21.5-29.5t-39.5-11.5z" />
<glyph unicode="&#xe64c;" glyph-name="uniE64C" d="M911 725h-242v123q0 21-13.5 34.5t-34.5 13.5h-246q-20 0-33.5-13.5t-13.5-34.5v-123h-246q-21 0-34.5-13.5t-13.5-34 13.5-34 34.5-13.5h829q21 0 34.5 13.5t13.5 34-13.5 34-34.5 13.5zM423 725v72h147v-72h-147zM765 579q-21 0-34.5-14t-13.5-34v-560h-441v560q0 20-13.5 34t-34 14-34-14-13.5-34v-611q0-21 13.5-34.5t34.5-13.5h536q20 0 33.5 13.5t13.5 34.5v611q3 20-11.5 34t-35.5 14zM447 67v389q0 20-13.5 33.5t-34 13.5-34-13.5-13.5-33.5v-389q0-21 13.5-34.5t34-13.5 34 13.5 13.5 34.5zM645 67v389q0 20-13.5 33.5t-34.5 13.5q-20 0-35.5-13.5t-15.5-33.5v-389q0-21 13.5-34.5t34.5-13.5 36 13.5 15 34.5z" />
<glyph unicode="&#xe64d;" glyph-name="uniE64D" d="M562 224h109v-111h-109v111zM889 224h109v-111h-109v111zM562 113h109v-110h-109v110zM438 458h-438v438h438v-438zM111 569h216v216h-216v-216zM1000 458h-438v438h438v-438zM673 569h216v216h-216v-216zM438-106h-438v438h438v-438zM111 5h216v216h-216v-216zM561 335h222v-111h-222v111zM889 334h109v-111h-109v111zM780 113h109v-111h-109v111zM562 2h218v-110h-218v110zM889 2h109v-110h-109v110z" />
<glyph unicode="&#xe900;" glyph-name="quan" d="M806.934 879.547h-604.98c-110.906 0-201.661-90.751-201.661-201.661v-604.982c0-110.91 90.755-201.66 201.661-201.66h604.98c110.918 0 201.663 90.75 201.663 201.66v604.982c-0.001 110.91-90.745 201.661-201.663 201.661zM850.766 187.323c-43.087 19.867-84.506 43.085-122.626 68.751-4.134-48.052-9.932-105.206-11.596-121.792-7.44-84.507-39.759-108.532-127.592-108.532h-121.793l-14.912 75.403h99.418c62.976 0 76.236 10.766 81.204 57.987 2.496 19.89 7.462 67.943 9.126 87.834h-179.802c-23.194-133.391-91.138-194.701-264.298-260.151l-43.086 80.349c147.483 43.085 198.019 87 217.898 179.802h-80.36v16.564c-38.939-28.993-83.687-57.156-134.222-84.508l-43.086 77.877c90.306 47.221 155.764 91.137 204.649 143.336h-183.106v73.74h238.62c12.429 19.89 23.194 40.601 33.14 63.796h-242.767v74.572h136.717l-75.405 96.937 66.291 44.737c28.162-34.791 67.111-84.507 95.273-120.962l-29.825-20.711h77.056c14.080 45.569 28.992 103.566 35.623 151.618l86.991-13.261c-9.934-49.704-20.7-95.273-32.309-138.358h111.849l-28.162 19.059c32.319 34.792 70.414 83.676 97.767 123.446l67.944-43.085c-22.387-29.826-52.213-68.764-78.71-99.42h138.356v-74.572h-333.071c-8.282-22.362-16.576-43.905-27.342-63.796h392.731v-73.74h-191.397c54.683-56.335 122.626-97.756 217.898-131.739l-43.086-81.182zM571.556 400.242h-141.673c-19.889-27.341-43.085-53.84-69.595-78.698h285.010c-26.521 24.026-51.379 50.525-73.742 78.698z" />
<glyph unicode="&#xe901;" glyph-name="notdef" horiz-adv-x="374" d="M34 0v682h272v-682h-272zM68 34h204v614h-204v-614z" />
<glyph unicode="&#xe900;" glyph-name="right" d="M370.851 73.927c-12.635-12.635-33.118-12.635-45.753 0l-251.641 251.641c-12.635 12.635-12.635 33.118 0 45.753v0c12.635 12.635 33.118 12.635 45.753 0l251.641-251.641c12.635-12.634 12.635-33.118 0-45.753v0zM325.361 74.19c-12.635 12.635-12.635 33.118 0 45.753l578.84 574.639c12.635 12.635 33.118 12.635 45.753 0v0c12.635-12.635 12.635-33.118 0-45.753l-578.84-574.639c-12.634-12.634-33.118-12.634-45.753 0v0z" />
<glyph unicode="&#xe901;" glyph-name="arrow-r" d="M835.918 379.851l-378.504 378.504 70.080 70.087 448.589-448.591-448.589-448.599-70.075 70.080 378.499 378.519zM423.154 386.889l-378.504 378.496 70.085 70.090 448.589-448.591-448.589-448.597-70.085 70.080 378.504 378.522z" />
<glyph unicode="&#xe902;" glyph-name="quan" d="M806.934 879.547h-604.98c-110.906 0-201.661-90.751-201.661-201.661v-604.982c0-110.91 90.755-201.66 201.661-201.66h604.98c110.918 0 201.663 90.75 201.663 201.66v604.982c-0.001 110.91-90.745 201.661-201.663 201.661zM850.766 187.323c-43.087 19.867-84.506 43.085-122.626 68.751-4.134-48.052-9.932-105.206-11.596-121.792-7.44-84.507-39.759-108.532-127.592-108.532h-121.793l-14.912 75.403h99.418c62.976 0 76.236 10.766 81.204 57.987 2.496 19.89 7.462 67.943 9.126 87.834h-179.802c-23.194-133.391-91.138-194.701-264.298-260.151l-43.086 80.349c147.483 43.085 198.019 87 217.898 179.802h-80.36v16.564c-38.939-28.993-83.687-57.156-134.222-84.508l-43.086 77.877c90.306 47.221 155.764 91.137 204.649 143.336h-183.106v73.74h238.62c12.429 19.89 23.194 40.601 33.14 63.796h-242.767v74.572h136.717l-75.405 96.937 66.291 44.737c28.162-34.791 67.111-84.507 95.273-120.962l-29.825-20.711h77.056c14.080 45.569 28.992 103.566 35.623 151.618l86.991-13.261c-9.934-49.704-20.7-95.273-32.309-138.358h111.849l-28.162 19.059c32.319 34.792 70.414 83.676 97.767 123.446l67.944-43.085c-22.387-29.826-52.213-68.764-78.71-99.42h138.356v-74.572h-333.071c-8.282-22.362-16.576-43.905-27.342-63.796h392.731v-73.74h-191.397c54.683-56.335 122.626-97.756 217.898-131.739l-43.086-81.182zM571.556 400.242h-141.673c-19.889-27.341-43.085-53.84-69.595-78.698h285.010c-26.521 24.026-51.379 50.525-73.742 78.698z" />
<glyph unicode="&#xe903;" glyph-name="notdef" horiz-adv-x="374" d="M34 0v682h272v-682h-272zM68 34h204v614h-204v-614z" />
</font></defs></svg>
\ No newline at end of file
... ...
No preview for this file type
No preview for this file type
<div class="slide-unlock">
<div class="bg" style="width: 0px;"></div>
<div class="label" style="left: 0px;"></div>
<span class="label-tip">向右滑动验证</span>
<div class="progress"></div>
</div>
\ No newline at end of file
... ...
... ... @@ -4,6 +4,7 @@
* @date: 2015/10/8
*/
var $ = require('yoho-jquery');
var SlideUnlock = require('plugin/slideunlock');
var $phoneNum = $('#phone-num'),
$countrySelect = $('#country-select'),
... ... @@ -11,6 +12,8 @@ var $phoneNum = $('#phone-num'),
$pwd = $('#pwd'),
$loginBtn = $('#btn-login'),
slideUnlock,
pnPass = false,
pwdPass = false;
... ... @@ -22,7 +25,7 @@ var showErrTip = tip.show;
// 登录按钮状态切换
function switchLoginBtnStatus() {
if (pnPass && pwdPass) {
if (pnPass && pwdPass && (slideUnlock && slideUnlock.isOk)) {
$loginBtn.removeClass('disable');
} else {
$loginBtn.addClass('disable');
... ... @@ -112,11 +115,20 @@ $loginBtn.on('touchstart', function() {
showErrTip('登录成功');
} else {
if (!slideUnlock && data.slideUnlock) {
slideUnlock = new SlideUnlock('#js-slideunlock', {}, switchLoginBtnStatus);
slideUnlock.init();
} else {
slideUnlock && slideUnlock.reset();
}
showErrTip(data.message);
}
},
error: function() {
showErrTip('网络断开连接啦~');
slideUnlock && slideUnlock.reset();
},
complete: function() {
$loginBtn.text('登录').removeClass('disable');
... ... @@ -128,6 +140,11 @@ $loginBtn.on('touchstart', function() {
}
});
if ($('#js-slideunlock').data('init') === true) {
slideUnlock = new SlideUnlock('#js-slideunlock', {}, switchLoginBtnStatus);
slideUnlock.init();
}
// 对初始有默认值的情况去初始化登录按钮状态
$phoneNum.trigger('input');
$pwd.trigger('input');
... ...
... ... @@ -4,6 +4,7 @@
* @date: 2015/9/30
*/
var $ = require('yoho-jquery');
var SlideUnlock = require('plugin/slideunlock');
var $account = $('#account'),
$pwd = $('#pwd'),
... ... @@ -12,6 +13,8 @@ var $account = $('#account'),
$mask = $('#retrive-pwd-mask'),
$ways = $('#retrive-pwd-ways'),
slideUnlock,
accPass = false,
pwdPass = false;
... ... @@ -23,7 +26,7 @@ var showErrTip = tip.show;
// 登录按钮状态切换
function switchLoginBtnStatus() {
if (accPass && pwdPass) {
if (accPass && pwdPass && (slideUnlock && slideUnlock.isOk)) {
$loginBtn.removeClass('disable');
} else {
$loginBtn.addClass('disable');
... ... @@ -96,11 +99,19 @@ $loginBtn.on('touchstart', function() {
showErrTip('登录成功');
location.href = res.href;
} else {
if (!slideUnlock && data.slideUnlock) {
slideUnlock = new SlideUnlock('#js-slideunlock', {}, switchLoginBtnStatus);
slideUnlock.init();
} else {
slideUnlock && slideUnlock.reset();
}
showErrTip(data.message);
}
},
error: function() {
showErrTip('网络断开连接啦~');
slideUnlock && slideUnlock.reset();
},
complete: function() {
$loginBtn.text('登录').removeClass('disable');
... ... @@ -126,6 +137,11 @@ $('#cancel-retrive').on('touchstart', function(e) {
hideRetrivePanel();
});
if ($('#js-slideunlock').data('init') === true) {
slideUnlock = new SlideUnlock('#js-slideunlock', {}, switchLoginBtnStatus);
slideUnlock.init();
}
// 对初始有默认值的情况去初始化登录按钮状态
$account.trigger('input');
$pwd.trigger('input');
... ...
/**
* jquery plugin -- jquery.slideunlock.js
* Description: a slideunlock plugin based on jQuery
* Version: 1.1
* Author: Dong Yuhao
* www.sucaijiayuan.com
* created: March 27, 2016
*/
function SliderUnlock(elm, options, success) {
var me = this;
var html = require('common/slide-unlock.hbs')();
var $c = me.checkElm(elm) ? $(elm) : $;
success = me.checkFn(success) ? success : function() {};
me.elm = $(html).replaceAll($c);
me.$progress = me.elm.find('.progress');
var opts = {
successLabelTip: '验证成功',
duration: 200,
swipestart: false,
min: 0,
max: me.elm.width(),
index: 0,
isOk: false,
lableIndex: 0
};
opts = $.extend(opts, options || {});
$(opts.html).appendTo($c);
// $elm
// opts
me.opts = opts;
// 是否开始滑动
me.swipestart = opts.swipestart;
// 最小值
me.min = opts.min;
// 最大值
me.max = opts.max;
// 当前滑动条所处的位置
me.index = opts.index;
// 是否滑动成功
me.isOk = opts.isOk;
// 滑块宽度
me.labelWidth = me.elm.find('.label').width();
// 滑块背景
me.sliderBg = me.elm.find('#slider_bg');
// 鼠标在滑动按钮的位置
me.lableIndex = opts.lableIndex;
// success
me.success = success;
return this;
}
SliderUnlock.prototype.init = function() {
var me = this;
me.updateView();
me.elm.find('.label').on('mousedown', function(event) {
if (me.isOk) {
return;
}
var e = event || window.event;
me.lableIndex = e.clientX - this.offsetLeft;
me.handerIn();
}).on('mousemove', function(event) {
if (me.isOk) {
return;
}
me.handerMove(event);
}).on('mouseup', function(event) {
if (me.isOk) {
return;
}
me.handerOut();
}).on('mouseout', function(event) {
if (me.isOk) {
return;
}
me.handerOut();
}).on('touchstart', function(event) {
if (me.isOk) {
return;
}
var e = event || window.event;
me.lableIndex = e.originalEvent.touches[0].pageX - this.offsetLeft;
me.handerIn();
}).on('touchmove', function(event) {
if (me.isOk) {
return;
}
me.handerMove(event, 'mobile');
}).on('touchend', function(event) {
if (me.isOk) {
return;
}
me.handerOut();
});
};
/**
* 鼠标/手指接触滑动按钮
*/
SliderUnlock.prototype.handerIn = function() {
var me = this;
me.swipestart = true;
me.min = 0;
me.max = me.elm.width();
};
/**
* 鼠标/手指移出
*/
SliderUnlock.prototype.handerOut = function() {
var me = this;
// 停止
me.swipestart = false;
// me.move();
if (me.index < me.max) {
me.reset();
}
};
/**
* 鼠标/手指移动
* @param event
* @param type
*/
SliderUnlock.prototype.handerMove = function(event, type) {
var me = this;
if (me.swipestart) {
event.preventDefault();
event = event || window.event;
if (type === 'mobile') {
me.index = event.originalEvent.touches[0].pageX - me.lableIndex;
} else {
me.index = event.clientX - me.lableIndex;
}
me.move();
}
};
/**
* 鼠标/手指移动过程
*/
SliderUnlock.prototype.move = function() {
var me = this;
if ((me.index + me.labelWidth) >= me.max) {
me.index = me.max - me.labelWidth - 2;
// 停止
me.swipestart = false;
// 解锁
me.isOk = true;
}
if (me.index < 0) {
me.index = me.min;
// 未解锁
me.isOk = false;
}
if (me.index + me.labelWidth + 2 === me.max && me.max > 0 && me.isOk) {
// 解锁默认操作
$('.label').next('.labelTip').
text(me.opts.successLabelTip).css({
color: '#fff'
});
me.success();
}
me.updateView();
};
/**
* 更新视图
*/
SliderUnlock.prototype.updateView = function() {
var me = this;
me.sliderBg.css('width', me.index);
me.elm.find('.label').css('left', me.index + 'px');
me.$progress.css('width', me.index + 'px');
me.elm.toggleClass('slide-unlock-ok', me.isOk);
};
/**
* 重置slide的起点
*/
SliderUnlock.prototype.reset = function() {
var me = this;
me.index = 0;
me.isOk = false;
me.sliderBg.animate({
width: 0
}, me.opts.duration);
me.elm.find('.label').animate({
left: me.index
}, me.opts.duration)
.next('#lableTip').animate({
opacity: 1
}, me.opts.duration);
me.updateView();
};
/**
* 检测元素是否存在
* @param elm
* @returns {boolean}
*/
SliderUnlock.prototype.checkElm = function(elm) {
if ($(elm).length > 0) {
return true;
} else {
throw 'this element does not exist.';
}
};
/**
* 检测传入参数是否是function
* @param fn
* @returns {boolean}
*/
SliderUnlock.prototype.checkFn = function(fn) {
if (typeof fn === 'function') {
return true;
} else {
throw 'the param is not a function.';
}
};
module.exports = SliderUnlock;
... ...
... ... @@ -12,6 +12,7 @@
/* component */
@import "layout/modal";
@import "layout/slide-unlock";
/* module */
... ...
.slide-unlock {
margin: 10PX auto 15PX;
height: 80px;
position: relative;
border-radius: 2px;
background-color: #b3b3b3;
border-radius: 5PX;
overflow: hidden;
text-align: center;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
.bg {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: #7ac23c;
z-index: 1;
}
.label {
width: 80px;
position: absolute;
left: 0;
top: 0;
height: 80px;
line-height: 80px;
outline: 1px solid #ccc;
border-radius: 4PX;
background: #e7e7e7;
z-index: 3;
cursor: move;
color: #ff9e77;
font-size: 16px;
font-weight: 900;
&:after {
display: block;
font-family: "iconfont";
content: "\e901";
color: #757575;
font-size: 25px;
}
}
.label-tip {
position: absolute;
left: 0;
width: 100%;
height: 100%;
font-size: 28px;
color: #787878;
line-height: 80px;
text-align: center;
z-index: 2;
}
.progress {
float: left;
height: 80px;
background-color: #36a74c;
}
}
.slide-unlock-ok .label:after {
content: "\e900" !important;
}
... ...