节点和角度。我有一个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(Node):
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);
}
我是否必须将令牌作为参数传递以检索用户详细信息?或者也可以将用户详细信息保存在单独的会话变量中?
答案 0 :(得分:20)
首先,使用Passport中间件进行用户授权处理是一种很好的做法。它需要解析您的请求的所有脏工作,并提供许多授权选项。 现在为您的Node.js代码。 您需要使用jwt方法验证并解析传递的令牌,然后通过从令牌中提取的id查找用户:
exports.me = function(req,res){
if (req.headers && req.headers.authorization) {
var authorization = headers.authorization,
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);
}
答案 1 :(得分:3)
从请求数据中找到令牌:
const usertoken = req.headers.authorization;
const token = usertoken.split(' ');
const decoded = jwt.verify(token[1], 'secret-key');
console.log(decoded);
答案 2 :(得分:2)
您正在使用两个回调调用函数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方法返回response object。确保您想要的不是$scope.myDetails = res.data
在您的Users.js文件中,您直接使用变量headers.authorization
,而它应该是req.header.authorization
:
var authorization = req.headers.authorization;
答案 3 :(得分:0)
根据文档https://github.com/themikenicholson/passport-jwt,您可以使用request.user
。请注意,我假设您使用的护照是带password-jwt的护照。
这是可能的,因为在身份验证上下文中的通行证正在设置请求对象并填充用户属性。因此,只需访问该属性。您不需要做中间件。
答案 4 :(得分:0)
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
}