nodejs使用express,crypto配合validator实现用户登录逻辑

来源:互联网 发布:淘宝商城招商 编辑:程序博客网 时间:2024/06/03 12:27

最近的项目使用express来写,这也是我尝试写的第一个nodejs的大型项目。今天实现了半天的登陆逻辑,还是很费劲的,在此记录一下。

大部分的知识都是从https://github.com/cnodejs/nodeclub 这份源码学到的,还有express官方的一个登陆验证示例

https://github.com/visionmedia/express/blob/master/examples/auth/app.js

当然还有api  http://expressjs.jser.us/api.html#res.status  但是吐槽一下,express的api。。真心崎岖。。

首先最坑的一点。。。让session生效

    app.use(express.cookieParser());//开启cookie    app.use(express.session({//开启session        secret: config.session_secret    }));    app.use(app.router);

那么注意了,前两行一定要写在app.router这个中间件前面!否则session始终未定义!

之后我们开始书写session与cookie配合的逻辑。

基本逻辑:

  • 进入网站后(此时没有session),从cookie中取加密的数据,进行验证,若验证成功,在session中存储user,用户免登陆。
  • 进入首页时(需要登录的页面),若session中没有user,则自动跳到登陆页面。
  • 登陆时,采用post方式提交用户信息,利用加密算法进行加密,存储登录信息到cookie中。
  • 数据库采用的mysql,采用啥都无所谓。。因为我是通过http与后端写好的统一登陆接口进行通信的。登陆成功返回0,失败返回-9999

ok,下面来一条条的实现这些逻辑。

首先我们利用crypto这个牛逼的加密加密库进行加密解密操作

var crypto = require('crypto');//加密function encrypt(str, secret) {    var cipher = crypto.createCipher('aes192', secret);    var enc = cipher.update(str, 'utf8', 'hex');    enc += cipher.final('hex');    return enc;}//解密function decrypt(str, secret) {    var decipher = crypto.createDecipher('aes192', secret);    var dec = decipher.update(str, 'hex', 'utf8');    dec += decipher.final('utf8');    return dec;}

他的作用主要是把用户名密码进行加密存到cookie,读取时解密。而密文我们在配置文件中配置即可。

第一个逻辑需要一个加密与解密的操作。而进入网站开始就进行操作的话,可以使用app.use中间件。

    app.use(express.cookieParser());//开启cookie    app.use(express.session({//开启session        secret: config.session_secret    }));    app.use(require('./controller/site').auth_user); // 添加这个中间件,用来解析cookie    app.use(app.router);

然后controller/side中auth_user如下

exports.auth_user = function (req, res, next) {    if (req.session.user) {        return next();//若没有session,直接跳过此中间件    } else {        var cookie = req.cookies[config.auth_cookie_name];//读cookie,通过配置文件中标识符读cookie        if (!cookie) {            return next();//若没有此站点的cookie,直接跳过此中间件        }        var auth_token = decrypt(cookie, config.session_secret);//解密操作        var auth = auth_token.split('\t');        var user = auth[0], passwd = auth[1];//解密后拿到username与password        var data = {            parament:user,            password:passwd,            route:'checkLogin',        }        var userLoginConf = config.apiService.userLogin;        postData.send(data, userLoginConf, function (result) {//这部分为post的api请求进行验证。            if (result == 0) {                req.session.user = user.username;//存在此用户,开启session,存储user                return next();//进行下一步            } else {//不存在此用户,进行下一步                return next();            }        })    }};

第二个逻辑很简单。我们直接使用一个私有函数即可。

/*session无效验证*/function noSession(req,res){    if (!req.session || !req.session.user) {        res.redirect('login');        return;    }}

第三个逻辑,配合router进行表单提交的工作

router:

    app.post('/login', site.login);

controller:

exports.login = function (req, res) {    /*处理空值与注入*/var param = handleParam(req.body)    var data ={        parament : param.username,        password: param.password,        route: 'checkLogin',    }    var userLoginConf = config.apiService.userLogin;    postData.send(data,userLoginConf,function(result){//与后端api接口通信        if(result ==0){//登陆成功            var user = {                'username':data.parament,                'password':data.password            }            gen_session(user, res);//生成cookie/*这个逻辑暂时没开,这是为了做那种“返回刚才页面”的需求            //check at some page just jump to home page            var refer = req.session._loginReferer || 'home';            for (var i = 0, len = notJump.length; i !== len; ++i) {                if (refer.indexOf(notJump[i]) >= 0) {                    refer = 'home';                    break;                }            }            res.redirect(refer);            */            req.session.regenerate(function(){//写session。存入username                // Store the user's primary key                // in the session store to be retrieved,                // or in this case the entire user object                req.session.user = user.username;                res.render('home',[]);//渲染数据,随便怎么渲染了。。            });        }else{            res.render('login',[]);//登录失败,跳转到login。这里我没有加提示信息。        }    })};

 这里处理注入使用了validator模块

var check = require('validator').check,    sanitize = require('validator').sanitize;/*处理空值与注入*/function handleParam(params){    var params = params || {};    var safeParam = {};    for(var key in params){        var trimed = sanitize(params[key]).xss();        var blockXssed = sanitize(trimed).xss();            safeParam[key] = blockXssed    }    return safeParam}

当然最后我们也要有个登出逻辑了

exports.logout = function (req, res, next) {//代码很简单,就不解释了    req.session.destroy();    res.clearCookie(config.auth_cookie_name, { path: '/' });    res.redirect(req.headers.referer || 'login');};

最后感谢写nodeclub  https://github.com/cnodejs/nodeclub 的各位,在你们的源码里学到了很多很多的东西!

0 0