文档章节

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

piggybear
 piggybear
发布于 2015/02/16 10:30
字数 1075
阅读 20
收藏 0

最近的项目使用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 的各位,在你们的源码里学到了很多很多的东西!

本文转载自:http://blog.csdn.net/aa294194253/article/details/41333839

共有 人打赏支持
piggybear
粉丝 3
博文 237
码字总数 37552
作品 0
西安
技术主管
私信 提问
Nodejs + Express 实现多用户博客系统(23 个视频)

Nodejs 实现最常见的登录注册功能,结合管理文章等功能,实现大家所期待的多用户博客系统。 总播放时长:135 分钟 作者:hfpp2012 类别:后端 技术分类:Nodejs Node.js + Express 实现多用户...

rails365
08/15
0
0
Node.js中的不安全跳转如何防御详解

Node.js中的不安全跳转如何防御详解 导语: 早年在浏览器大战期间,有远见的Chrome认为要运行现代Web应用,浏览器必须有一个性能非常强劲的Java引擎,于是Google自己开发了一个高性能的开源的...

开元中国2015
昨天
0
0
如何防御Node.js中的不安全跳转

         什么是不安全的重定向?   对于任何web开发人员来说,不安全或未经验证的重定向都是重要的安全考虑因素。Express为重定向提供了本地支持,使它们易于实现和使用。然而,Exp...

嘶吼RoarTalk
10/09
0
0
spring boot——ajax跨域

前言 java语言在多数时,会作为一个后端语言,为前端的php,node.js等提供API接口。前端通过ajax请求去调用java的API服务。今天以node.js为例,介绍两种跨域方式:CrossOrigin和反向代理。 一...

吴金瑞
06/26
0
0
新手如何快速入门node.js

我当初学的时候,是在大大们的指导下开始学习的,用了3天搞定大大们给的任务。下面我就把这个经历分享出来,让大家借鉴一下。欢迎吐槽~~ 任务如下: 根据Node js 开发入门教程第五章的一个使...

rin9958
2016/03/28
132
0

没有更多内容

加载失败,请刷新页面

加载更多

php isset,emtpy,is_null,真假值判断小记

<?phpheader("Content-type:text/html; charset='utf-8'");echo "<pre>";$a = '';$b = ' ';$c = "\r\n";$d = 0;$e = false;$f = null;var_dump(strlen($a),strlen($b),str......

病态S
11分钟前
0
0
PHP 关于常用函数的使用总结

strpos() 函数返回字符串在另一个字符串中第一次出现的位置。   如果没有找到该字符串,则返回 false。 strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。该函数返回字符串的其余...

koothon
13分钟前
0
0
Groovy秘诀

Groovy秘诀 听说java世界里有个Groovy大神!java需要半天处理的事情,Groovy只需要几分钟,是的,几分钟…剩下来的时间,程序员终于有时间泡妹子了,^_^…….技术宅的兄弟,赶紧来看看吧。 首...

白石
19分钟前
0
0
不能在FROM子句中为更新指定目标表 (You can't specify target table 'xxx' for update in FROM clause )

在select外边套一层,让数据库认为你不是查同一表的数据作为同一表的更新数据: update user_basic set is_new=1 where id IN( SELECT a.id FROM ( SELECT user_basic.id FROM user_basic,st...

郭周园
24分钟前
0
0
idea上实现github代码同步

https://www.cnblogs.com/liangzhilin/p/6106090.html

踏破铁鞋无觅处
27分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部