在后端(Nodejs + Express)上,我使用JWT令牌保护了路由。在开发环境中,请求中的HTTP授权标头如下所示:
$arr_file_types = ['application/pdf'];
我构建了角度应用程序后,出于某种原因构建的应用程序在标头中添加了“ Bearer”:
Authorization: JWT token_string
请求:
Authorization: Bearer JWT token_string
节点:
addTemplate(template: ITemplate): Observable<ISuccessMsgResponse> {
return this.http.post<ISuccessMsgResponse>(`${this.ULR}template`, template, {
headers: new HttpHeaders({
'Authorization': this.token.getToken()
})
});
}
护照:
.post(passport.authenticate('jwt', {session: false}), (req, res) => {
// Code to execute
}
如果我尝试使用与开发中相同的Authorization标头格式进行请求,则一切正常。因此问题出在Angular的内置版本中,该版本在Authorization标头中添加了“ Bearer”。有谁知道为什么会这样以及我该如何解决?
答案 0 :(得分:1)
我知道已经过了半年,但仍然只是想发布我的问题的答案。
在这种情况下的问题是,在开发中,HttpClient
没有在'Authorization'标头的开头附加'Bearer'字符串,但是在生产中将其包括在内。
发展:JWT token_string
生产:Bearer JWT token_string
解决方案非常烦人,因为我不得不手动在构建脚本中找到Authorization Header所在的部分,并删除设置了标头的字符串中的“ JWT”,因为看起来其中需要Bearer。 >
之前:Bearer JWT token_string
之后:Bearer token_string
在后端,还必须修改用于提取的字符串。 之前:
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, (jwtPayload, done) => {
User.findById(jwtPayload._id, (err, user) => {
if(err) {
return done(err, false);
}
if(user) {
return done(null, user);
} else {
return done(null, false);
}
});
}));
之后:
let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('bearer');
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, (jwtPayload, done) => {
User.findById(jwtPayload._id, (err, user) => {
if(err) {
return done(err, false);
}
if(user) {
return done(null, user);
} else {
return done(null, false);
}
});
}));
我不在这个主题中导出,但是我真的不明白为什么不会在开发中(如在生产中)添加“ Bearer”的原因。可能只是一个错误(Angular 7)。 IDK。
答案 1 :(得分:1)
距离上次回答还有很长一段时间,但它可能对某人有所帮助 - 并防止一些痛苦,就像我的一样,直到我想出一个“解决方案”。
简而言之,请求是:
getUserProfile(){
this.loadCurrentToken();
const headers = new HttpHeaders({
'Content-Type': 'application/json',
Authorization: this.authToken,
});
console.log(headers);
return this.http.get('/users/profile', {headers});
}
我面临的问题是,在开发模式 (ng serve) 中,在授权标头处生成的令牌的形式为:JWT eyfhik4u5h4tb...等,在生产模式 (ng build --prod),'Bearer' 词被添加为前缀,所以现在令牌是:Bearer JWT eyfhik4u5h4tb...等(就像上面的答案所暗示的那样)
当然这是标准,但也不想从 fromAuthHeaderWithScheme('jwt') 方法更改为提取方法,意思是:
let opts ={};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
User.getUserById(jwt_payload._id, (err, user) => {
if(err){
return done(err, false);
}
if(user){
return done(null, user);
} else {
return done(null, false);
}
});
}));
...对于其他内容,让我们说 fromAuthHeaderWithScheme(auth_scheme) 或 fromAuthHeaderAsBearerToken() 并继续进行相应的更改。
所以,我所做的,并且到目前为止在生产和开发模式下都运行良好,是尝试获得一个“干净”的令牌 - 以 JWT eyfhik4u5h4tb...等的形式无论是开发环境还是生产环境。
我的方法是这样修改 //node_modules/passport-jwt/lib/auth_headers.js 文件:
'use strict';
var re = /(\S+)\s+(\S+)/;
function parseAuthHeader(hdrValue) {
if (typeof hdrValue !== 'string') {
return null;
}
/* ADDED THIS LINE */
hdrValue = hdrValue.substring(hdrValue.indexOf('JWT') + 0);
/* --------------- */
var matches = hdrValue.match(re);
// console.log(hdrValue);
return matches && { scheme: matches[1], value: matches[2] };
}
module.exports = {
parse: parseAuthHeader
};
所以,现在,提取器将只关心以 JWT 开头的令牌部分,并忽略不记名前缀 - 或任何前缀 - 如果存在。
当然,使用这种方法应该记住的一点是,在部署应用程序时,应该包括特定的、更改的、passport-jwt 模块,因为在 npm-install 时,该模块将重新启动/更新等,并且不会工作。