Authored by 梁志锋

登录支持验证码。

module.exports=function(app) {
app.get("/captcha", "captcha_create", function (captcha, req, res){
res.writeHead(200, {
'Content-Type': 'image/png'
});
res.end(captcha);
});
app.post("/checkCaptchaImg", "captcha_checkCaptchaImg", function (captcha, req, res){
return res.json(captcha);
});
}
... ...
... ... @@ -9,9 +9,19 @@ module.exports=function(app) {
app.post("/login", "common_login", function (login, req, res){
if (login.code == 200) {
res.myRedirect('/');
} else {
res.myRedirect('/login');
//res.myRedirect('/');
return res.json({
code: 200,
message: login.message
});
} else if(login.code == 400){
return res.json({
code: 400,
message: login.message,
data: {
needCaptcha: login.needCaptcha
}
});
}
});
... ...
'use strict';
var _ = require('lodash');
var Captchapng = require('captchapng');
var Utils = {
generateCaptcha: function (width, height, length) {
var min = Math.pow(10, (length - 1 || 1));
var max = Math.pow(10, (length - 1 || 1)) * 9;
var token = '' + _.random(min, max);
var png = new Captchapng(width, height, token);//
png.color(0, 0, 0, 0); // First color: background (red, green, blue, alpha)
png.color(80, 80, 80, 255); // Second color: paint (red, green, blue, alpha)
return {
image: new Buffer(png.getBase64(), 'base64'),
text: token
};
}
};
module.exports = {
namespace: "captcha",
apis: {
create: function (req, callback) {
var width = req.query.w || 150;
var height = req.query.h || 50;
var length = +(req.query.l || 4);
var captcha = Utils.generateCaptcha(width, height, length);
req.session.captcha = captcha.text;
return callback(null, captcha.image);
},
checkCaptchaImg: function (req, callback) {
var captchaToken = req.body.verifyCode || '';
if (captchaToken === req.session.captcha) {
return callback(null, {
code: 200,
message: '验证成功'
});
} else {
return callback(null, {
code: 400,
message: '您输入的验证码不正确!'
});
}
}
}
};
\ No newline at end of file
... ...
... ... @@ -81,48 +81,45 @@ module.exports = {
},
login: function (req, callback, common) {
var userInfo = {},result = { code: 400, message: "登录失败" },isSuccess=false;
var user = req.body.user;
var password = req.body.password;
var errcallback = function (err) {
return callback(err, result);
}
//promise.all(Ilogin,allRight,sessionAsync).then(a,b,c);
var user = req.body.user||req.query.user;
var password = req.body.password||req.query.password;
var errcallback = function (err) {
return callback(null, result);
};
var loginErrcallback = function (err) {
req.session.captchaErrorTimes +=1 ;
console.log(req.session.captchaErrorTimes);
result.needCaptcha = true;
return callback(null, result);
};
common.Ilogin(user, password).allRight().sessionAsync(user, password).done(function (IloginRes,allRes,sesRes) {
var userData = IloginRes.data, cookie = sesRes.caseless.dict["set-cookie"];
userInfo = { auth: userData, uid: userData.pid, name: userData.truename, right: {},shopList:[]};
allRes.data.forEach(function (data) {
if (data.platform_id == Iaccount.WEBSITE) {
userInfo.right[data.path] = true;
}
});
common.getResourceByPid(userData.pid, userData.role_id)
.getShopList({ "@x-user-id": userInfo.uid }).done(function (getRRes, shopRes) {
userInfo.menu = Utils.createrMenus(getRRes.data);
if (shopRes.data) {
shopRes.data.forEach(function (data, index) {
if (!index) {
userInfo.auth.shopName = data.shopName;
userInfo.auth.shopId = data.shopsId;
}
userInfo.shopList.push({
name: data.shopName,
id: data.shopsId
});
});
common.Ilogin(user, password).done(function (IloginRes) {
var userData = IloginRes.data,
userInfo = { auth: userData, uid: userData.pid, name: userData.truename, right: {},shopList:[],brands:[]};
if(userData.data_authority&&userData.data_authority.brand&&userData.data_authority.brand.list){
userInfo.brands=userData.data_authority.brand.is_all?"0":Object.keys(userData.data_authority.brand.list);
}
req.session.captchaErrorTimes = 0 ;
common.allRight().sessionAsync(user, password).done(function (allRes,sesRes) {
var cookie = sesRes.caseless.dict["set-cookie"];
allRes.data.forEach(function (data) {
if (data.platform_id == Iaccount.WEBSITE) {
userInfo.right[data.path] = true;
}
});
common.getResourceByPid(userData.pid, userData.role_id).done(function (getRRes) {
userInfo.menu = Utils.createrMenus(getRRes.data);
req.session.user = userInfo;
if (cookie && cookie.length > 0) {
req.session.gray = cookie[0];
result = { code: 200, message: "登录成功" };
result = { code: 200, message: "登录成功" ,data:req.session.user};
}
console.log(result);
return callback(null, result);
},errcallback);
} else {
result = { code: 400, message: "该用户没有店铺" };
}
return callback(null, result);
},errcallback);
}, errcallback);
}, errcallback);
}, loginErrcallback);
},
isUsedMenuAuth:{
title:'检查有没有权限',
... ...
... ... @@ -20,7 +20,7 @@
</div>
</div>
<div class="login-content">
<form action="/login" method="POST" class="margin-bottom-0">
<form method="POST" class="margin-bottom-0" onsubmit='return false;'>
<input type="hidden" name="refer" value="%2F">
<div class="form-group m-b-20">
<input type="text" class="form-control input-lg" name="user" placeholder="用户名" autocomplete="off" />
... ... @@ -28,8 +28,17 @@
<div class="form-group m-b-20">
<input type="password" class="form-control input-lg" name="password" placeholder="密码" autocomplete="off" />
</div>
<div class="input-group mb15 captcha-wrap hide">
<input type="text" name="captcha" id="captcha" class="form-control" placeholder="图形验证码" autocomplete="off" maxlength="4">
<img id="captcha-img" class="captcha-img" alt="">
<a class="link change-captcha">换一张</a>
<span class="err-tip hide">
<i></i>
<em></em>
</span>
</div>
<div class="login-buttons">
<button type="submit" class="btn btn-success btn-block btn-lg">&nbsp;&nbsp;</button>
<button id="login-btn" type="submit" class="btn btn-success btn-block btn-lg">&nbsp;&nbsp;</button>
</div>
</form>
</div>
... ...
module.exports=function(Filter){
Filter.define("/!(login)", ["get","post"], "common_gray", function (gray, req, res, next){
Filter.define("/!(login|captcha|checkCaptchaImg)", ["get","post"], "common_gray", function (gray, req, res, next){
if(gray.code==200){
next();
}else{
... ...
... ... @@ -22,7 +22,8 @@
"mkdirp": "^0.5.1",
"request": "^2.72.0",
"winston": "^2.2.0",
"glob": "^7.0.3"
"glob": "^7.0.3",
"captchapng": "0.0.1"
},
"devDependencies": {
"autoprefixer-loader": "^3.2.0",
... ...
'use strict';
var $ = require('jquery');
// 图像验证码URL
var CAPTCHA_IMG_URL = 'captcha?t=',
$captchaImgInput = $('#captcha'),
$captchaImgWrapper = $('.captcha-wrap'),
$captchaImgPic = $captchaImgWrapper.find('#captcha-img'),
$captchaImgTip = $captchaImgInput.siblings('.err-tip');
// click登录
$('#login-btn').on('click', loginAsync);
/** ************************************************************************/
/* 登录函数 */
/** ************************************************************************/
function loginAsync() {
return validateCaptchaImg().then(function() {
return $.ajax({
url: 'login/',
type: 'POST',
dataType: 'json',
data: {
user: $('#user').val(),
password: $('#password').val()
}
});
}).then(function(res) {
if (res.code === 200) {
location.href = '/';
} else if (res.code === 400){
if (res.data.needCaptcha) {
$captchaImgTip.removeClass('hide')
.children('em');
$captchaImgInput.addClass('error').val('');
showCaptchaImgPic();
} else {
location.href = '/';
}
}
});
}
/** ************************************************************************/
/* 验证码刷新 */
/** ************************************************************************/
$captchaImgWrapper.on('click', '.change-captcha, .captcha-img', function() {
$captchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
});
/** ************************************************************************/
/* 显示验证码 */
/** ************************************************************************/
function showCaptchaImgPic() {
$captchaImgPic.attr('src', CAPTCHA_IMG_URL + $.now());
$captchaImgInput.val('');
$captchaImgWrapper.removeClass('hide');
}
/** ************************************************************************/
/* 验证验证码是否正确 */
/** ************************************************************************/
// 图像验证码输入框事件
$captchaImgInput.on('blur', validateCaptchaImg);
function validateCaptchaImg() {
// 验证码不可见的时候验证通过
if ($captchaImgWrapper.is(':hidden')) {
return $.Deferred().resolve().promise(); //eslint-disable-line
}
return validateCaptchaImgLocal()
.then(validateCaptchaImgAsync);
}
function validateCaptchaImgAsync() {
return $.ajax({
url: 'checkCaptchaImg/',
type: 'POST',
dataType: 'json',
data: {
verifyCode: getCaptchaImgVal()
}
}).then(function(result) {
var defer = $.Deferred(); // eslint-disable-line
if (result.code === 200) {
hideCaptchaImgTip();
defer.resolve();
} else {
showCaptchaImgTip('验证码不正确');
defer.reject();
}
return defer.promise();
});
}
function validateCaptchaImgLocal() {
var captcha = getCaptchaImgVal(),
err;
var defer = $.Deferred(); // eslint-disable-line
if (captcha !== '') {
if (captcha.length !== 4) {
err = '请输入长度为4字符的验证码';
defer.reject();
} else {
defer.resolve();
}
} else {
err = '请输入验证码';
defer.reject();
}
if (defer.state() === 'resolved') {
hideCaptchaImgTip();
} else {
showCaptchaImgTip(err);
}
return defer.promise();
}
function getCaptchaImgVal() {
return $.trim($captchaImgInput.val());
}
function hideCaptchaImgTip() {
return errTipHide($captchaImgTip, $captchaImgInput);
}
function showCaptchaImgTip(msg) {
return errTipShow($captchaImgTip, $captchaImgInput, msg);
}
function errTipHide($tip, $input) {
$tip.addClass('hide');
$input.removeClass('error');
}
function errTipShow($tip, $input, msg) {
$tip.removeClass('hide').children('em').empty().html(msg);
$input.addClass('error');
}
\ No newline at end of file
... ...