谁来简单的介绍一下Nodejs下登录验证和权限的标准做法?

谁来简单的介绍一下Nodejs下登录验证和权限的标准做法?

我是一只小小小菜鸟,对于nodejs中的session和登录以及权限有不理解的地方,目前我登录这边是这么做的: 1.请求登录,验证用户名密码,通过后记录req的sessionid和用户名,权限,存成名值对放在全局变量中 2.在cookie中记录用户名,以后每次请求都判断sessionid和用户名、权限是否和存储的一致 3.30分钟内无操作删除req的sessionid和用户名、权限的名值对

我想问问,大家是怎么利用session、cookie、nodejs做登录和权限验证的? 求各位介绍一下自己的基本流程,说说大意即可


6 回复

当然可以。下面我会介绍一个基于 Node.js 的典型登录验证和权限管理的标准做法,并提供一些示例代码。

基本概念

  1. Session:用于在服务器端存储用户会话信息。
  2. Cookie:客户端存储会话标识符(如 session ID),以便后续请求能够关联到同一个会话。
  3. 中间件:用于处理请求和响应的函数,可以在请求到达路由之前或之后执行特定的操作。

使用 Express 和 express-session 中间件

首先,你需要安装 expressexpress-session

npm install express express-session

示例代码

1. 设置 Session

const express = require('express');
const session = require('express-session');

const app = express();

app.use(session({
    secret: 'your_secret_key', // 用于加密 session id 的密钥
    resave: false,
    saveUninitialized: true,
    cookie: { maxAge: 30 * 60 * 1000 } // 30分钟
}));

app.get('/login', (req, res) => {
    // 假设用户名和密码正确
    req.session.user = {
        username: 'testUser',
        role: 'admin'
    };
    res.send('Login successful!');
});

app.get('/profile', (req, res) => {
    if (req.session.user) {
        res.send(`Welcome ${req.session.user.username}! Your role is ${req.session.user.role}.`);
    } else {
        res.redirect('/login');
    }
});

app.listen(3000, () => console.log('Server running on port 3000'));

解释

  1. 设置 Session:使用 express-session 中间件来管理 session。secret 是用来加密 session ID 的密钥,确保安全性。maxAge 指定 session 的有效期。

  2. 登录逻辑:当用户访问 /login 路由时,我们假设用户名和密码是正确的,并将用户信息存储在 req.session.user 中。然后重定向到其他页面。

  3. 权限检查:在需要权限检查的路由(如 /profile)中,检查 req.session.user 是否存在。如果存在,则显示用户信息;否则,重定向到登录页面。

总结

这种做法通过 express-session 来管理 session,利用 cookie 存储 session ID,并通过中间件在每个请求中自动加载 session 数据。这种方式比直接在全局变量中存储数据更安全和高效。


请参考 nodeclub 源码

谢谢,我看懂了

我没有看明白,请问有没有像J2EE 那样的过滤器或者Struts2那样的拦截器之类的东西来判断用户登录状态?

我跟你想的一样,就自己写了个,可以试试npm install rainbow,仓库地址:https://github.com/mytharcher/rainbow

在Node.js中处理登录验证和权限管理时,通常使用中间件(如express-session)来管理会话,并使用JWT(JSON Web Tokens)或基于Cookie的机制来处理用户身份验证和权限。下面是基于这些常用技术的一个简单标准做法。

基本流程

  1. 登录请求:客户端发送包含用户名和密码的登录请求。
  2. 验证用户:服务器端验证用户名和密码的有效性。
  3. 生成Token或设置Session:验证成功后,生成JWT Token或设置express-session,并将相关信息(如用户ID、角色等)存储在Token或Session中。
  4. 返回Token或Session ID:将Token或Session ID返回给客户端。
  5. 后续请求认证:客户端在后续请求中附带Token或Session ID,服务器验证Token或检查Session以确认用户身份。
  6. 权限控制:根据用户的角色或权限级别进行资源访问控制。

示例代码

假设我们使用express, express-sessionbcrypt库来处理密码哈希,以及jsonwebtoken来生成JWT Token。

const express = require('express');
const session = require('express-session');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const app = express();

app.use(express.json());
app.use(session({
    secret: 'your_secret_key',
    resave: false,
    saveUninitialized: true,
}));

// 用户数据库模拟
const users = [
    { id: 1, username: 'admin', password: '$2b$10$QnDyRJGZPzF8mHk7KqUvN.gi7wTjGzXtEzVgOz9Xf1C' }, // 密码为'password'
];

app.post('/login', async (req, res) => {
    const { username, password } = req.body;

    const user = users.find(u => u.username === username);
    if (!user || !(await bcrypt.compare(password, user.password))) {
        return res.status(401).send('Unauthorized');
    }

    // 生成JWT Token
    const token = jwt.sign({ userId: user.id, role: 'admin' }, 'your_jwt_secret', { expiresIn: '1h' });

    // 或者设置Session
    // req.session.user = { userId: user.id, role: 'admin' };

    res.json({ token });
});

app.get('/protected', verifyToken, (req, res) => {
    res.send('You have access to this protected route.');
});

function verifyToken(req, res, next) {
    const token = req.headers['authorization'];

    if (!token) return res.status(403).send('A token is required for authentication');

    try {
        const decoded = jwt.verify(token, 'your_jwt_secret');
        req.user = decoded;
    } catch (err) {
        return res.status(401).send('Invalid Token');
    }
    return next();
}

app.listen(3000, () => console.log('Server running on port 3000'));

在这个例子中,我们首先验证了用户名和密码,然后生成了一个JWT Token。客户端在后续请求中携带该Token,服务器使用verifyToken中间件来解码并验证Token,从而决定是否允许访问受保护的路由。

这种方法相比直接操作全局变量更安全,也更容易扩展。

回到顶部