【问题标题】:JWT Token Verification to decode and Protect Routes in MEAN AppJWT 令牌验证以解码和保护 MEAN 应用程序中的路由
【发布时间】: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 }

【问题讨论】:

    标签: node.js angular express authentication jwt


    【解决方案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 的帮助。
    • 如果它有帮助并且你觉得它是一个正确的答案,也许你应该接受这个答案或支持它。它将激励我和其他用户帮助他人。
    猜你喜欢
    • 2021-03-10
    • 2019-11-22
    • 1970-01-01
    • 2013-09-11
    • 2020-11-17
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    相关资源
    最近更新 更多