请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

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

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


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

正在回答 回答被采纳积分+3

1回答

提问者 Yoooshiki 2018-08-10 22:14:21

首先说一下,我上面说的放到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 回复 有任何疑惑可以回复我~
  • 桂圆 #1
    你好,我是用django的,按照你的登录状态存储在redis中,是不是就能实现单点登录呢,跟sso和ldap之间啥区别呢
    回复 有任何疑惑可以回复我~ 2020-01-15 08:15:17
  • 提问者 Yoooshiki 回复 桂圆 #2
    是可以实现单点登录,至于区别嘛没什么区别,实现方式不同而已。就比如有些人实现鉴权喜欢用框架,我就不喜欢用框架,自己写逻辑会更灵活一些
    回复 有任何疑惑可以回复我~ 2020-01-15 11:06:43
  • 桂圆 回复 提问者 Yoooshiki #3
    请问找到老师session放到哪里了吗,10-1视频直接是req.session.user=doc,没看懂
    回复 有任何疑惑可以回复我~ 2020-08-16 08:28:48
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号