使用本地策略生成令牌有效,并且令牌可以使用 JwtService 进行验证
validate(token)
但在使用 @UseGuards(AuthGuard('jwt'))
时则不行
这有效:
// auth.controller.ts
// ...
@Post(`/verify`)
async verify(@Request() req, @Headers() headers) {
const authHeader = headers['authorization'] // manually get the Authorization header value
const token = authHeader.substring('Bearer '.length) // This will remove the Bearer prefix
return this.jwtService.verify(token)
}
这不是:
// auth.controller.ts
// ...
@UseGuards(AuthGuard('jwt'))
@Post(`/verify`)
async verify(@Request() req, @Headers() headers) {
return(req.user)
}
秘密已在 jwt 策略配置中正确设置
import { Injectable } from '@nestjs/common'
import { PassportStrategy } from '@nestjs/passport'
import { ExtractJwt, Strategy } from 'passport-jwt'
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: `${process.env.JWT_SECRET}`,
})
}
async validate(username: string, password: string) {
return { username, password }
}
}
以及模块中
// auth.module.ts
// ...
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
MongooseModule.forFeature([
{
name: User.name,
schema: UserSchema,
},
]),
JwtModule.register({
secret: `${process.env.JWT_SECRET}`,
signOptions: {
expiresIn: '60d',
},
}),
],
controllers: [AuthController],
providers: [
AuthService,
UserService,
HashService,
LocalStrategy,
JwtStrategy,
],
})
export class AuthModule {}
最后,当尝试使用自定义
@UseGuards(JwtAuthGuard)
而不是 @UseGuards(AuthGuard('jwt'))
进行处理时,我可以在 canActivate()
中正确读取令牌,但 handleRequest()
(仍然)返回授权并在日志中显示“Jsonwebtokenerror:无效签名”
// jwt-gaurd.ts
import { ExecutionContext, Injectable } from '@nestjs/common'
import { AuthGuard } from '@nestjs/passport'
import { JwtService } from '@nestjs/jwt'
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
constructor(private jwtService: JwtService) {
super({
secret: `${process.env.JWT_SECRET}`,
signOptions: {
expiresIn: '60d',
},
})
}
async canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest()
const token = request.headers.authorization.split(' ')[1]
try {
const payload = await this.jwtService.verify(token)
console.log(payload) // logs correctly
super.canActivate(context)
return true
} catch (error) {
return false
}
}
async validate(payload: any) {
return payload
}
handleRequest(err, user, info) {
console.log(err, user, info)
if (err || !user) {
return err
}
return user
}
}
如上所示,我尝试在多个位置提取令牌,它正确验证并获取有效负载。
我确保我的导入与有关错误的现有线程保持一致,并记录了秘密以确保它在任何地方都是正确的。
不知道为什么除了守卫装饰器之外,一切都可以按预期工作。任何帮助对我的理智都非常有价值。
这最终对我有用,Nest 文档现在建议扩展 CanActivate 而不是 AuthGuard('jwt') 来保护端点
我遇到了同样的问题,并找到了适合我的具体情况的解决方案。 问题是
jwt.sign(token)
没有使用模块提供的秘密进行签名。
尝试首先在 jwt.io 中创建 jwt 令牌(使用您的 SECRET_TOKEN)进行验证,然后在您的服务中进行验证。如果有效 -> 您的 jwt.verify()
至少可以正常工作。
然后尝试通过调用 jwt.sign(token, {secret: SECRET_TOKEN})
从您的服务生成 jwt 令牌。在 jwt.io 中并通过您的服务验证签名令牌。