授权中间件 JWT 混淆

Posted

技术标签:

【中文标题】授权中间件 JWT 混淆【英文标题】:Authorization middleware JWT confusion 【发布时间】:2021-04-16 00:33:07 【问题描述】:

我怀疑我在参加的课程中遇到的一些身份验证中间件代码的相对安全性。

所以我使用邮递员向受保护的路线发送请求(请参阅下面的路线代码),发现我能够使用为另一个用户生成的令牌检索一个用户的订单。

const protected = asyncHandler(async (req, res, next) => 
  let token;
  if (
    req.headers.authorization &&
    req.headers.authorization.startsWith("Bearer")
  ) 
    try 
      token = req.headers.authorization.split(" ")[1];
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      req.user = await User.findById(decoded.id).select("-password");

  next();
 catch (error) 
  console.error(error);
  res.status(401);
  throw new Error("Not authorized, token failed");

 
  if (!token) 
    res.status(401);
    throw new Error("Not authorized, No token found");
  
); 
export protected

在我看来,这个中间件代码只会验证来自解码令牌的用户是否存在于数据库中,但不会根据用户/令牌限制对资源的访问。

import addOrderItems, getOrderbyId  from "../controllers/orderController.js";
import  protected  from "../middleware/authMiddleware.js";
    
const router = express.Router();

router.route("/").post(protected, addOrderItems);
router.route("/:id").get(protected, getOrderbyId);
//:id is the order id

但是,当测试另一个受保护的路由以更新用户的个人资料信息时,我在使用错误的令牌时收到错误消息。

希望得到一些澄清

【问题讨论】:

此代码本身仅验证 jwt 令牌是否有效并匹配数据库中的某个用户。它不做任何其他事情来控制该用户可以或不能访问哪些数据。顺便说一句,asyncHandler() 是什么? @jfriend00 它的中间件用于处理快速异步函数中的异常。检查此link。感谢您的澄清。想了很多 @jfriend00 你觉得这个策略怎么样:我想在我的用户数据库模型/文档中添加一个名为 tokens 的数组字段。然后我会检查令牌字段是否匹配令牌。如果令牌字段不存在匹配项,则抛出错误(未授权) 令牌不一定是永久的,所以我不会将它们用作永久密钥。我不知道您的应用程序,但也许记录可能包含授权用户 ID 列表?或者,如果记录只属于一个用户,那么每个用户都应该有自己的记录列表,并且您的服务器只查找属于当前授权用户的记录。根据应用的整体需求,有很多不同的方式来构建事物。 【参考方案1】:

jwt.verify 只会验证给定的令牌是否由服务器生成。它不关心哪个用户发送了这个令牌。

对于受保护的中间件,它只检查请求是否被授权。如果是这样,请求将传递给控制器​​。

关于更新路线。大概是这样的:

// route 
router.route("/:userId", protected, updateController)

const updateController = (req, res) => 
  const user = req.user; // this is the one generated by protected middleware
  const reqUserId = req.params.userId; // this is the one send by request
  
  if (user.id !== reqUserId) 
      // if two ids are not the same, it means someone is trying
      // to update the profile with the wrong token
      res.status(401);
  

  // update profile in database

【讨论】:

以上是关于授权中间件 JWT 混淆的主要内容,如果未能解决你的问题,请参考以下文章

Postgraphile + express + jwt 正在抛出“未找到授权令牌”,即使 graphiql 有效

基于角色的 jwt 授权

在 Ocelot API 网关中间件中返回未授权

JWT 授权 laravel / angularjs 问题

laravel 8 -> 使用 jwt 和邮递员授权

NodeJs:错误401(未经授权)我正在使用passport-jwt