You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GET请求中验证用户身份?(React+Node.js+Express场景)

解决方案:给文件访问接口添加登录验证中间件

你的核心问题是文件访问接口没有校验用户登录状态,所以任何人都能直接通过URL访问。我们可以通过给/source/:fileid接口添加一个登录验证中间件来解决,下面分两种常用方案说明:

方案一:基于Session的验证(适配当前登录流程)

这种方式利用Express的session机制,登录成功后在服务器端保存用户会话,后续请求会自动携带session cookie供服务器验证,非常适合你现在的登录逻辑。

步骤1:安装依赖

先安装会话管理相关包,其中connect-pg-simple用来把session存储到PostgreSQL,避免服务器重启后会话丢失:

npm install express-session connect-pg-simple

步骤2:配置Express Session

在server.js里添加session配置(记得替换成你自己的数据库连接和安全密钥):

const session = require('express-session');
const pgSession = require('connect-pg-simple')(session);
const db = require('./你的数据库连接文件'); // 替换为你实际的DB连接

// 配置session
app.use(session({
  store: new pgSession({
    pool: db, // 复用你的PostgreSQL连接池
    tableName: 'session' // 需要提前在数据库创建该表,脚本可参考connect-pg-simple的官方文档
  }),
  secret: '你的随机安全密钥', // 替换成复杂的随机字符串,用于加密session
  resave: false,
  saveUninitialized: false,
  cookie: {
    maxAge: 24 * 60 * 60 * 1000, // 会话有效期1天
    secure: process.env.NODE_ENV === 'production', // 生产环境开启HTTPS时设为true
    httpOnly: true // 禁止前端JS读取cookie,提升安全性
  }
}));

步骤3:修改登录接口,存储用户会话

在signin.js的登录成功逻辑中,把用户信息存入session:

// 登录成功后返回用户信息前
.then(user => {
  req.session.user = user[0]; // 将用户信息存入session
  res.json(user[0])
})

步骤4:编写登录验证中间件

在server.js中添加一个中间件,用于检查用户是否已登录:

const requireAuth = (req, res, next) => {
  // 检查session中是否存在有效用户信息
  if (req.session.user) {
    next(); // 已登录,继续执行后续路由逻辑
  } else {
    res.status(401).json('请先登录'); // 未登录,返回401状态码
  }
};

步骤5:给文件接口添加验证中间件

修改/source/:fileid路由,将验证中间件前置:

app.get('/source/:fileid', requireAuth, (req, res) => {
  const { fileid } = req.params;
  // (可选)如果需要权限细分,这里可以额外校验:当前用户是否有权访问该文件
  res.sendFile(__dirname + '/data/' + fileid);
});

这样一来,未登录用户直接访问文件URL时,服务器会返回401,浏览器无法加载图片;登录后,浏览器会自动携带session cookie,服务器验证通过后返回文件。


方案二:基于JWT的验证

如果你的应用是纯前后端分离架构,JWT也是常用的身份验证方式。注意img标签无法自定义请求头,所以我们把JWT存入HttpOnly Cookie:

步骤1:安装依赖

npm install jsonwebtoken cookie-parser

步骤2:登录成功返回JWT并设置Cookie

修改signin.js:

const jwt = require('jsonwebtoken');

// 登录成功后
.then(user => {
  const token = jwt.sign({ userId: user[0].id }, '你的JWT密钥', { expiresIn: '1d' });
  // 将JWT存入HttpOnly Cookie
  res.cookie('token', token, {
    maxAge: 24 * 60 * 60 * 1000,
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true
  });
  res.json(user[0])
})

步骤3:编写JWT验证中间件

在server.js中:

const jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');

app.use(cookieParser());

const requireAuth = (req, res, next) => {
  const token = req.cookies.token;
  if (!token) {
    return res.status(401).json('请先登录');
  }
  try {
    const decoded = jwt.verify(token, '你的JWT密钥');
    req.user = decoded; // 将解码后的用户信息存入req对象
    next();
  } catch (err) {
    res.status(401).json('无效的登录凭证');
  }
};

步骤4:给文件接口添加中间件

和方案一一致,将requireAuth加到文件路由前即可。


额外优化点

  • 如果需要文件权限细分(比如用户只能访问自己上传的文件),在/source/:fileid接口中还要额外查询数据库,验证当前登录用户是否有权限访问该文件。
  • React端的img标签在收到401时会显示加载失败,你可以通过onError事件处理,比如显示默认图片:
<img 
  alt='文件预览' 
  src={`http://example.com/source/${filename}`}
  onError={(e) => { e.target.src='/path/to/default-empty-image.png'; }}
/>

内容的提问来源于stack exchange,提问作者JKhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:32:33