NodeJs-从JWT令牌中检索用户信息

NodeJs - Retrieve user information from JWT token?

本文关键字:检索 用户 信息 令牌 JWT NodeJs-      更新时间:2023-09-26

节点和角度。我有一个MEAN堆栈身份验证应用程序,我在成功登录时设置JWT令牌,如下所示,并将其存储在控制器的会话中。通过服务拦截器将JWT令牌分配给config.headers:

var token = jwt.sign({id: user._id}, secret.secretToken, { expiresIn: tokenManager.TOKEN_EXPIRATION_SEC });
            return res.json({token:token});

authservice.js拦截器(省略requestError、response和responseError):

authServices.factory('TokenInterceptor', ['$q', '$window', '$location','AuthenticationService',function ($q, $window, $location, AuthenticationService) {
        return {
            request: function (config) {
                config.headers = config.headers || {};
                if ($window.sessionStorage.token) {
                    config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
                }
                return config;
            }               
        };
    }]);

现在我想从令牌中获取登录用户的详细信息,我该怎么做?我试了如下,但没有成功。当我从Users.js文件中记录错误时,它说"ReferenceError:headers is not defined"

authController.js:

$scope.me = function() {
    UserService.me(function(res) {
      $scope.myDetails = res;
    }, function() {
      console.log('Failed to fetch details');
      $rootScope.error = 'Failed to fetch details';
    })
  };

authService.js:

authServices.factory('UserService',['$http', function($http) {
  return {        
    me:function() {
    return $http.get(options.api.base_url + '/me');
    }
  }
}]);

Users.js(节点):

 exports.me = function(req,res){
    if (req.headers && req.headers.authorization) {
        var authorization =req.headers.authorization;
        var part = authorization.split(' ');
        //logic here to retrieve the user from database
    }
    return res.send(200);
}

为了检索用户详细信息,我是否也必须将令牌作为参数传递?还是将用户详细信息保存在单独的会话变量中?

首先,使用Passport中间件进行用户授权处理是一种很好的做法。它承担了解析请求的所有脏活,还提供了许多授权选项。现在是您的Node.js代码。您需要使用jwt方法验证和解析传递的令牌,然后通过从令牌中提取的id找到用户:

exports.me = function(req,res){
    if (req.headers && req.headers.authorization) {
        var authorization = req.headers.authorization.split(' ')[1],
            decoded;
        try {
            decoded = jwt.verify(authorization, secret.secretToken);
        } catch (e) {
            return res.status(401).send('unauthorized');
        }
        var userId = decoded.id;
        // Fetch the user by id 
        User.findOne({_id: userId}).then(function(user){
            // Do something with the user
            return res.send(200);
        });
    }
    return res.send(500);
}

从请求数据中查找令牌:

const usertoken = req.headers.authorization;
const token = usertoken.split(' ');
const decoded = jwt.verify(token[1], 'secret-key');
console.log(decoded);

您正在使用两个回调调用函数UserService.me,尽管该函数不接受任何参数。我想你想做的是:

$scope.me = function() {
    UserService.me().then(function(res) {
      $scope.myDetails = res;
    }, function() {
      console.log('Failed to fetch details');
      $rootScope.error = 'Failed to fetch details';
    });
  };

另外,请注意$http方法返回一个响应对象。确保您想要的不是$scope.myDetails = res.data

在Users.js文件中,您直接使用变量headers.authorization,而它应该是req.header.authorization:

var authorization = req.headers.authorization;

根据文档https://github.com/themikenicholson/passport-jwt,您可以使用request.user。注意,我假设你使用的是jwt护照。这是可能的,因为passport在身份验证的上下文中设置了请求对象并填充了用户属性。所以,只需访问该属性。您不需要做中间件。

Anderson anzileiro是正确的。如果您在中间件代码中返回完整的令牌,那么请求中确实填充了用户属性,并且您可以访问您的配置文件。

passport.use(
  new JWTstrategy(
    {
      secretOrKey: process.env.ACCESS_TOKEN_SECRET,
      // jwtFromRequest: ExtractJWT.fromUrlQueryParameter('secret_token')
      jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken()
    },
    async (token, done) => {
      try {
        return done(null, token);
      } catch (error) {
        done(error);
      }
    }
  )
);

req.user将返回:

{
    "user": {
        "username": "admin"
    },
    "iat": 1625920948,
    "exp": 1626007348
}