【发布时间】:2020-02-22 14:35:43
【问题描述】:
这篇文章已经被编辑了好几次,所以我用更相关的方式重写了这篇文章
[!] 我所有的代码都是股票here,请参阅master 分支。请记住:代码在本地工作,但不在我的服务器上。
Tl;博士
在本地(start:dev 或 start:prod)一切正常,在我的服务器(start:dev 或 start:prod)我的 jwt 验证不起作用。我拿回了令牌,但如果我在受保护的路线上测试它,我得到了一个 401...
日志
一些日志(在产品中)。
1 - 我在domain.dev/api/hello 中发送了一个获取请求(通过邮递员)
Request Headers
User-Agent: "PostmanRuntime/7.19.0"
Accept: "*/*"
Cache-Control: "no-cache"
Postman-Token: "3940ba0e-3c60-4746-bb12-e06bf01df0bf"
Host: "domain.dev"
Accept-Encoding: "gzip, deflate"
Connection: "keep-alive"
Response Headers
Date: "Sun, 27 Oct 2019 20:54:35 GMT"
Server: "Apache/2.4.25 (Debian)"
X-Powered-By: "Express"
Access-Control-Allow-Origin: "*"
Content-Type: "text/html; charset=utf-8"
Content-Length: "12"
ETag: "W/"c-Lve95gjOVATpfV8EL5X4nxwjKHE""
Keep-Alive: "timeout=5, max=100"
Connection: "Keep-Alive"
Response Body
Hello World!
服务器响应,好的!
2 - 我在domain.dev/api/auth 中发送一个帖子请求(通过邮递员)
Request Headers
Content-Type: "application/json"
User-Agent: "PostmanRuntime/7.19.0"
Accept: "*/*"
Cache-Control: "no-cache"
Postman-Token: "4391992e-788c-4780-b188-833999383704"
Host: "alanbouteiller.dev"
Accept-Encoding: "gzip, deflate"
Content-Length: 45
Connection: "keep-alive"
Request Body
name: "Hadock"
password: "XXXXXX"
Response Headers
Date: "Sun, 27 Oct 2019 20:57:14 GMT"
Server: "Apache/2.4.25 (Debian)"
X-Powered-By: "Express"
Access-Control-Allow-Origin: "*"
Content-Type: "application/json; charset=utf-8"
Content-Length: "212"
ETag: "W/"d4-XWUV7P7Ft81OyIDhImoZoNDfnsA""
Keep-Alive: "timeout=5, max=100"
Connection: "Keep-Alive"
Response Body
access_token:
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSGFkb2NrIiwic3ViIjoiNWQ4YTFmZGIyMDc3NTU0NjlmMjgzNDNlIiwiaWF0IjoxNTcyMjEwMDY3LCJleHAiOjE1NzIyMTAxODd9.hoe69wy86XXXXXXXXXXXXXghGVw8TEKmOA"
代码中每条日志对应:
- 红色 ->
auth.controller.ts
// give the jwt
@Post()
async login(@Request() req): Promise<any> {
console.log(req.body); // the red
return await this.authService.login(req.body);
}
- 橙绿蓝紫->
auht.service.ts
@Injectable()
export class AuthService {
constructor(
@InjectModel('Author') private readonly authorModel: Model<AuthorInterface>,
private readonly authorService: AuthorService,
private readonly jwtService: JwtService,
) {}
// check if user exist in db, if is return user
async validateUser(name: string): Promise<any> {
const user = await this.authorService.getAuthorByName(name);
console.log(user); // orange 1
if (user.length !== 0) {
console.log({status: true, data: user[0]}); // orange 2
return {status: true, data: user[0]};
} else {
return {status: false, data: 'no user with this name'};
}
}
// check user and return token if user is valid
async login(author: any) {
const check = await this.validateUser(author.name);
console.log(check); // orange 3
if (check.status) {
console.log(author.password); // green
console.log(check.data.password); // green
const compare = await bcrypt.compare(author.password, check.data.password);
if (!compare) {
// if check is not ok
return {status: false, message: 'bad credential'};
} else {
// generate jwt payload
const payload = {name: author.name, sub: check.data._id};
console.log(payload); // blue
const jwt = this.jwtService.sign(payload);
console.log(jwt); // purple
// save in db
await this.authorModel.updateOne({_id: check.data._id}, {$set: {token: jwt}});
// return
return {access_token: jwt};
}
} else {
return {status: false, message: 'no user found'};
}
}
}
一切看起来都不错...令牌在 db 和响应中是相同的。
但是;我在jwt.strategy.ts 中验证的函数永远不会被调用:
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy} from '@nestjs/passport';
import {Injectable, UnauthorizedException} from '@nestjs/common';
import { ConfigService } from '../conf/config.service';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(env: ConfigService) {
super({
// which the jwt is extracted
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
// the password module check the expiration, this class no
ignoreExpiration: false,
secretOrKey: env.get('secret'),
});
}
// this function is call automatically by the @UseGuards(AuthGuard('jwt'))
async validate(payload: any) {
console.log('----------validate');
console.log(payload);
console.log({ username: payload.name, userId: payload.sub, timeStamp: new Date() });
return !payload ? new UnauthorizedException() : { username: payload.name, userId: payload.sub, timeStamp: new Date() };
}
}
console.log 在日志中不可见,而在本地使用相同的文件时会出现这种情况:
// LOCAL LOG WHIT THE SAME BUILD FOLDER
{ name: 'hadock', password: 'test' }
[
{
_id: 5d7e6520c7e8fb43fcb1a1e5,
name: 'hadock',
password: '$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q',
__v: 0,
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMTc2ODkxLCJleHAiOjE1NzIxNzcwMTF9.8RnXXXXXXXX2rjwXs'
}
]
{
status: true,
data: {
_id: 5d7e6520c7e8fb43fcb1a1e5,
name: 'hadock',
password: '$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q',
__v: 0,
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMTc2ODkxLCJleHAiOjE1NzIxNzcwMTF9.8RnXXXXXXXX2rjwXs'
}
}
{
status: true,
data: {
_id: 5d7e6520c7e8fb43fcb1a1e5,
name: 'hadock',
password: '$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q',
__v: 0,
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMTc2ODkxLCJleHAiOjE1NzIxNzcwMTF9.8RnXXXXXXXX2rjwXs'
}
}
test
$2b$12$f8bUfYwr7jjPlDuIrKVtzuKMZRVVRWjUUIOJpdSaeoFv4PN5XQ57q
{ name: 'hadock', sub: 5d7e6520c7e8fb43fcb1a1e5 }
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaGFkb2NrIiwic3ViIjoiNWQ3ZTY1MjBjN2U4ZmI0M2ZjYjFhMWU1IiwiaWF0IjoxNTcyMjEyNDI5LCJleHAiOjE1NzIyMTI1NDl9.MrjXXXXXXXXX4NLFNw
----------validate
{
name: 'hadock',
sub: '5d7e6520c7e8fb43fcb1a1e5',
iat: 1572212429,
exp: 1572212549
}
{
username: 'hadock',
userId: '5d7e6520c7e8fb43fcb1a1e5',
timeStamp: 2019-10-27T21:40:47.206Z
}
【问题讨论】: