将登录状态放到session真的好吗?

来源:10-1 登录功能实现

Yoooshiki

2018-08-10

老师您好,我是做Java的,一般来说,我们不会将登录状态放到session中,因为如果是分布式系统,有多台服务器的话,每一次的请求不一定落到哪台服务器,因此我们的常用套路是做分布式session,也就是将登录状态保存到redis中,然后多数需要做权限认证的接口都会做拦截,查询redis中是否有用户的登录状态。


这里的话是直接将状态保存到session中吗?应该也可能存在分布式的情况吧?

写回答

1回答

Yoooshiki

提问者

2018-08-10

首先说一下,我上面说的放到session里不好,指的是放到服务器内存。而且我down下来了老师的代码,没发现将状态保存到session的,所以晚上用了点时间,自认为算是完美解决吧:


$ npm install uuid
$ npm install redis


一、登录、登出功能


//Redis
let redis = require('redis')
let client = redis.createClient()
//uuid
const uuidv4 = require('uuid/v4')   //v4是随机数
//登录
router.post('/login', function (req, res, next) {
    let param = {
        userName: req.body.userName,
        userPwd: req.body.userPwd
    }
    User.findOne(param, (err, doc) => {
        if (err) {
            res.json({
                status: "1",
                msg: err.message
            })
        } else {
            let uuid = uuidv4()
            //存至cookie
            res.cookie("token", uuid, {
                path: "/",
                maxAge: 1000 * 60 * 60   //存储1小时
            })
            //存至redis, 1小时失效
            client.set(`token-${uuid}`, JSON.stringify(doc))
            client.expire(`token-${uuid}`, 60 * 60);
            res.json({
                status: "0",
                msg: "",
                result: doc.userName
            })
        }
    })
});

//登出
router.post('/logout', function (req, res, next) {
    let cookie = req.cookies.token
    if (cookie) {
        //清除redis
        client.del(`token-${cookie}`)
        //清除cookie
        res.cookie("token", "", {
            path: "/",
            maxAge: 0
        })
    }
    res.json({
        status: "0",
        msg: "",
        result: ""
    })
});



二、登录拦截功能


//Redis
let redis = require('redis')
let client = redis.createClient()
client.on('ready', function (err) {
    console.log('Redis ready');
});
//拦截放在路由之前,只要有请求进来就先判断的
app.use(function (req, res, next) {
    //接口白名单
    if (
        req.originalUrl == '/users/login' ||
        req.originalUrl == '/users/logout' ||
        req.path == "/goods/list"     //因为后面有参数,只取接口的pathName. 或者 req.originalUrl.indexOf('/goods/list') > -1
    ){
        next()
        return
    }
    //验证登录状态
    let cookie = req.cookies.token
    //查询cookie
    if (!cookie) {
        res.statusCode = 401
        res.json({
            status: '401',
            msg: '当前未登录',
            result: ''
        });
    }
    //查询redis
    client.get(`token-${cookie}`, (err, reply) => {
        if (!reply) {
            res.statusCode = 401
            res.json({
                status: '401',
                msg: '当前未登录',
                result: ''
            });
        }else next()
    })
});
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/goods', goodsRouter);


这样的话,如果没有登录,响应码设置为401,前端就可以通过axios拦截器拦截到401,跳转到登录页或者提醒登录。

0
3
桂圆
回复
Yoooshiki
请问找到老师session放到哪里了吗,10-1视频直接是req.session.user=doc,没看懂
2020-08-16
共3条回复

Vue2.6+Node.js+MongoDB 全栈打造商城系统

课程全面升级,Vue2.6+Koa2,从前端入门全栈,让你的未来更宽广

2634 学习 · 924 问题

查看课程