如何将用户凭据附加到 expressjs 中的请求管道?

Posted

技术标签:

【中文标题】如何将用户凭据附加到 expressjs 中的请求管道?【英文标题】:How to attach user credentials to the request pipeline in expressjs? 【发布时间】:2022-01-16 11:39:59 【问题描述】:

我正在尝试编写一个中间件来提取用户模型并将其附加到请求管道。 我已经编写了一个令牌提取器中间件并设法将令牌附加到请求管道,但由于某种原因,当我尝试提取用户模型时,它在中间件函数内工作正常,但在我的控制器内它返回为未定义。

这是我尝试过的:

utils/middleware.js

const tokenExtractor = async (request, response, next) =>     
        const authorization = await request.get('authorization');
       if (authorization && authorization.toLowerCase().startsWith('bearer ')) 
         request.token = authorization.substring(7);         
        else
         request.token = null;
        
        next();
;

const userExtractor = async (request, response, next) =>   
  tokenExtractor(request, response, next);
  if(request.token)
    const decodedToken = jwt.verify(request.token, process.env.SECRET);    
    request.user = await User.findById(decodedToken.id);
    console.log(request.user); // Works
    next();
   else
    response.status(403).json( error: 'no token received' );
  
;

在我的控制器内部它发生故障:

controllers/blogs.js

blogRouter.post("/", async (request, response, next) => 
  if (request.body.title && request.body.url) 
    const token = request.token;    
    if (!token) 
      return response.status(401).json( error: 'invalid token' );
    
      
    console.log(request.user); // undefined !
    if(!request.user)
      return response.status(401).json( error: 'invalid user' );
    
    
    const user = request.user;    
    
    const blog = new Blog(
      title: request.body.title,
      author: request.body.author,
      url: request.body.url,
      likes: request.body.likes,
      user: user._id,
    );

    
    await blog.save();    
    
    user.blogs = user.blogs.concat(blog._id);
    await user.save();
    
    response.status(201).json(blog);
  
  response.status(400).end();
);

这两个中间件都已附加到 express 应用。

编辑:

我已通过从 userExtractor 函数中删除对 tokenExtractor 的调用来解决此问题,然后将中间件链接到路由器而不是先调用它们。

我在全局使用 tokenExtractor,而在本地使用 userExtractor 到 blogsRouter。发生的事情是,虽然 tokenExtractor 工作正常,但 blogRouters 在 userExtractor 被调用之前就被调用了,因此我没有定义。

app.js

// app.use(tokenExtractor);
app.use(requestLogger);
app.use(errorHandler);
// app.use(userExtractor);

app.use('/api/login', tokenExtractor, loginRouter);
app.use('/api/users', usersRouter);
app.use('/api/blogs', tokenExtractor, userExtractor, blogRouter); // chaining the extractors

【问题讨论】:

【参考方案1】:

有道理,让next()(req, res, next) 实例作为管道 向前传递。不需要任何 hack,您可以根据需要堆叠任意数量的中间件,甚至可以在另一个中间重用值 - 如果您可以信任调用堆栈的顺序。

【讨论】:

以上是关于如何将用户凭据附加到 expressjs 中的请求管道?的主要内容,如果未能解决你的问题,请参考以下文章

如何将用户凭据传递给 Web 服务?

请求端点相同的应用程序 Expressjs?

如何允许无限制的发布请求 expressjs

ExpressJS / Angular 2 JWT 令牌

带有 NuxtJS 中间件的 ExpressJS 将发布数据传递到页面

将登录凭据附加到URL