JWT 令牌验证以解码和保护 MEAN 应用程序中的路由

Posted

技术标签:

【中文标题】JWT 令牌验证以解码和保护 MEAN 应用程序中的路由【英文标题】:JWT Token Verification to decode and Protect Routes in MEAN App 【发布时间】:2021-12-06 23:08:05 【问题描述】:

我正在尝试使用 JWT 对用户进行身份验证。我在登录时分配了一个令牌。

if (client) 
      // Check if Client does exist, then compare password provided by Client
      if (!req.body.password) 
        res.json( success: false, message: "No password provided" ); // Password was not provided
       else 
        var validPassword = client.password === req.body.password; // Check if password matches password provided by Client
        if (!validPassword) 
          res.json( success: false, message: password: message: "Incorrect Password" ); // Password does not match password in database
         else 
          if (!client.active) 
            res.json( success: false, message: active: message: "Account is not activated" ); // Account is not activated
           else 
            var token = jwt.sign(
               username: client.username, email: client.email ,
              secret,
               expiresIn: "24h" 
            ); // Logged in: Give Client token
            res.json(
              success: true,
              message: "Client authenticated!",
              token: token
            ); // Return token in JSON object to controller
          
        
      
    

登录后,我正在检查请求中的令牌使我成为用户。

router.use(function(req, res, next)    
var token = req.body.token || req.body.query || req.headers['x-access-token']; // Check for token in body, URL, or headers
// Check if token is valid and not expired  
if (token) 
// Function to verify token
    jwt.verify(token, secret, (err, decoded) => 
        if (err) 
            res.json( success: false, message: 'Token invalid' ); // Token has expired or is invalid
         else 
            req.decoded = decoded; // Assign to req. variable to be able to use it in next() route ('/me' route)
            next(); // Required to leave middleware
        
    );
 else 
    res.json( success: false, message: 'No token provided' ); // Return error if no token was provided in the request
   

);

我将所有受保护的路由放在检查令牌之后。用户可以访问个人资料页面/me

router.post('/me', function(req, res) 
    res.send(req.decoded); // Return the token acquired from middleware
);

如何在 Angular 11 中检查 req.body 中的令牌?我曾尝试使用 localStorage 设置令牌,但似乎我做得不对。

localStorage.setItem('userToken', response.token);

通过在正文中传递令牌访问 /me 路由时,它似乎在 Postman 中工作正常。它显示是否找到令牌。如果找到则显示结果

“电子邮件”:“example@gmail.com”, "iat": 1634704834, “exp”:1634791234

【问题讨论】:

【参考方案1】:

一切似乎都很好。我认为,您只需要在前端实现一个拦截器。它将从本地存储中选择身份验证令牌,并将其附加到所有请求中。

示例代码

import  HttpRequest, HttpHandler, HttpEvent, HttpInterceptor  from '@angular/common/http';
import  Observable  from 'rxjs';
import  AuthService  from './service/auth.module';

@Injectable()
export class AuthInterceptor implements HttpInterceptor 
    constructor(private authService: AuthService)  

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
        let loggedInUser = this.authService.currentUserValue;
        token = JSON.parse(localStorage.getItem(user.token));
        if (token) 
            request = request.clone(
                setHeaders: 
                    Authorization: `Bearer $token`
                
            );
        

        return next.handle(request);
    

是的,在正文参数中发送身份验证令牌并不是一个好习惯。安全的方法是始终对此类敏感信息使用标题。更多详情可查看here

【讨论】:

感谢 Pankaj 的帮助。我按照建议使用了 HttpInterceptor 。它似乎工作正常。 如果你认为我的回答有帮助或者它是正确的答案,也许你应该投票/接受这个答案。【参考方案2】:

我用过HttpInterceptor

import  Injectable, Injector  from '@angular/core';
import  HttpInterceptor  from '@angular/common/http';
import  AuthService  from './auth.service';

@Injectable()
export class TokenInterceptorService implements HttpInterceptor 
  constructor(private injector: Injector) 
  intercept(req, next) 
    let auth = this.injector.get(AuthService);
    let tokenizedReq = req.clone(
      setHeaders: 
        Authorization: `Bearer $auth.getToken()`,
      ,
    );
    return next.handle(tokenizedReq);
  

它反映了标头中的令牌,但当我尝试从任何路由上的后端获取数据时提示“令牌无效”。我正在使用console.log(response); 进行检查,而它在 nodemon 中工作正常,同时在标头中传递令牌。

请帮忙。

【讨论】:

您的陈述不清楚。请编辑或添加更多详细信息,您所面临的问题究竟是什么。 抱歉,我是 Angular 新手。使用 HttpInterceptor 后,我可以在请求标头中获取令牌,但是当我访问路由时,它会显示 Token Invalid 并且没有从后端呈现数据。不知何故,登录时提供的令牌和请求标头令牌不匹配。在请求标头和 localStorage 令牌中手动检查令牌时,两者是相同的。甚至邮递员在传递令牌后也在渲染数据,但它没有在前端渲染。 我很确定,这要归功于 Bearer $token 。从令牌中删除 Bearer,它将起作用。所以在你的 HttpInterceptor 中,使用这个授权:$auth.getToken(),(从中删除 Bearer) 感谢 Pankaj 的帮助。 如果它有帮助并且你觉得它是一个正确的答案,也许你应该接受这个答案或支持它。它将激励我和其他用户帮助他人。

以上是关于JWT 令牌验证以解码和保护 MEAN 应用程序中的路由的主要内容,如果未能解决你的问题,请参考以下文章

客户端应用 jwt 令牌解码和验证安全

DocuSign 获取 JWT 令牌 MEAN Stack

Golang REST API - 从经过验证和解码的令牌传递信息

使用带有 RSA 的 JWT 解码 Id 令牌

在每个API调用之前验证JWT令牌

如何解码我在 Swift 中收到 REST API 的 JWT 令牌?