当前位置: 首页 > 知识库问答 >
问题:

巢js Auth Guard JWT Authentication不断返回401个未经授权的

郜琦
2023-03-14

使用Postman测试我的endpoint,我能够成功“登录”并接收JWT令牌。现在,我正在尝试访问一个应该有AuthGuard的endpoint,以确保现在我已经登录,现在可以访问它。

但是,即使在Postman中显示了JWT令牌,它也会不断返回401非授权

这是我的代码:

user.controller.ts

@Controller('users')
export class UsersController {
    constructor(private readonly usersService: UsersService) {}

    @UseGuards(AuthGuard())
    @Get()
    getUsers() {
        return this.usersService.getUsersAsync();
    }
}

jwt。策略输电系统

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
    constructor(
        private readonly authenticationService: AuthenticationService,
    ) {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            ignoreExpiration: false,
            secretOrKey: 'SuperSecretJWTKey',
        });
    }

    async validate(payload: any, done: Function) {
        console.log("I AM HERE"); // this never gets called.
        const user = await this.authenticationService.validateUserToken(payload);

        if (!user) {
            return done(new UnauthorizedException(), false);
        }

        done(null, user);
    }
}

我试过提取JWT。fromAuthHeaderWithScheme('JWT')也一样,但这不起作用。

authentication.module.ts

@Module({
    imports: [
        ConfigModule,
        UsersModule,
        PassportModule.register({ defaultStrategy: 'jwt' }),
        JwtModule.register({
            secret: 'SuperSecretJWTKey',
            signOptions: { expiresIn: 3600 },
        }),
    ],
    controllers: [AuthenticationController],
    providers: [AuthenticationService, LocalStrategy, JwtStrategy],
    exports: [AuthenticationService, LocalStrategy, JwtStrategy],
})
export class AuthenticationModule {}

authentication.controller.ts

@Controller('auth')
export class AuthenticationController {
    constructor(
        private readonly authenticationService: AuthenticationService,
        private readonly usersService: UsersService,
    ) {}

    @UseGuards(AuthGuard('local'))
    @Post('login')
    public async loginAsync(@Response() res, @Body() login: LoginModel) {
        const user = await this.usersService.getUserByUsernameAsync(login.username);

        if (!user) {
            res.status(HttpStatus.NOT_FOUND).json({
                message: 'User Not Found',
            });
        } else {
            const token = this.authenticationService.createToken(user);
            return res.status(HttpStatus.OK).json(token);
        }
    }
}

在Postman中,我能够使用登录endpoint使用适当的凭据成功登录,并接收JWT令牌。然后,我向GET请求添加一个身份验证头,复制并粘贴到JWT令牌中,我尝试了“承载”和“JWT”方案,都返回401个未经授权的消息,如下图所示。

我不知道这里会有什么问题。任何帮助都将不胜感激。

共有3个答案

裴心水
2023-03-14

我也有同样的问题

在我的情况下,验证endpoint参数电子邮件密码,而嵌套身份验证留档声明它们应该是用户名密码,如下所示

js prettyprint-override">async validate(username: string, password: string): Promise<any> {
    const user = await this.authService.validateUser(username, password);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }

还要注意在请求正文中发送用户名和密码

信用:https://github.com/nestjs/docs.nestjs.com/issues/875#issuecomment-619472086

慕容坚
2023-03-14

我也有同样的问题。我的问题是JwtModule secret和JwtStrategy secretrokey不同。希望这可能会帮助一些人坚持这一点!

东门奕
2023-03-14

请注意,只有在成功验证JWT后,才会调用JWT策略中的validate()函数。如果您在尝试使用JWT时始终得到401响应,那么您不能期望调用此函数。

来自validate()方法的返回被注入到由JWT身份验证保护的任何操作的请求对象中。

我不确定您正在调用的完成()函数,但这是我当前项目中的一个有效的验证()方法:

async validate(payload: JwtPayload): Promise<User> {
  const { email } = payload
  const user = await this.authService.getActiveUser(email)

  if (!user) {
    throw new UnauthorizedException()
  }

  return user
}

看起来您希望返回用户的想法是正确的。确保这就是authenticationService。validateUserToken()实际上是这样。

在该策略中,jwtFromRequest:ExtractJwt。fromAuthHeaderAsBearerToken()似乎正确,在Postman中使用带有承载令牌的授权标头也看起来正确。

关于您的身份验证。控制器。ts文件,请注意直接在NestJS中的控制器内使用请求和响应对象。它们访问底层框架,例如Express,并且容易绕过Nest实现的许多功能。提到https://docs.nestjs.com/faq/request-lifecycle看看你跳过了什么。。。

您可以直接从NestJS中修饰的控制器方法(例如@Get()Post()等)返回对象并抛出错误,框架将处理其余部分:HTTP代码、JSON等。

从您的控制器中,考虑放弃@Reponse res并使用抛出新的UnAuthizedException('User不被发现')和简单的返回{Token}(或类似)方法。

在您的受保护路由中,我发现显式声明AuthGuard('jwt')效果更好,并且在某些情况下不会产生警告,即使您确实将默认策略设置为JWT。

你真的需要登录路径上的AuthGuard('local')?

在您的loginAsync()方法中,不要忘记使用有效负载对令牌进行实际签名的关键步骤。您没有在身份验证服务中提供用于方法实现的代码,但我怀疑这可能是您缺少的。

考虑登录服务的这个工作实现(它只是由它的控制器的登录函数调用):

  async login(authCredentialsDto: AuthCredentialsDto): Promise<{ accessToken: string }> {
    const { email, password } = authCredentialsDto

    const success = await this.usersRepository.verifyCredentials(email, password)

    if (!success) {
      throw new UnauthorizedException('Invalid credentials')
    }

    // roles, email, etc can be added to the payload - but don't add sensitive info!
    const payload: JwtPayload = { email } 
    const accessToken = this.jwtService.sign(payload)

    this.logger.debug(`Generated JWT token with payload ${JSON.stringify(payload)}`)

    return { accessToken }
  }

注意,通过将私有jwtService:jwtService添加到构造函数参数,通过依赖注入将jwtService注入到类中。

还要注意在上面如何为JwtPayload定义接口,以便显式地键入它。这比在代码中使用任何代码都要好。

最后,如果您的JWT仍然无法验证,请绝对确保您在Postman中正确使用了令牌。请格外小心,不要添加前导/尾随空格、换行符等。我自己也犯了这个错误。您可能希望通过编写一个快速JS文件来测试API,并发出一个获取请求,将授权头设置为值Bearer${token}

我希望这有帮助,祝你好运!

 类似资料:
  • 所以,我试图用Tweepy喜欢一个推文,但是这个错误正在发生: 有什么想法吗?

  • 我正在使用postman,并尝试通过http://localhost:8180/auth/admin/realms/demo/users/{userID}更新用户的配置文件,但收到响应。 通过http://localhost:8180/auth/admin/realms/demo/users/{userID}发送带有Json内容类型和用户信息的Put请求。 不幸的是,我已经连续收到了401个回复。

  • 在这个留档Spring Security MVC Test中描述了如何使用Spring Security测试安全的ressource。我遵循了提供的所有步骤,但访问受保护的ressource仍然会返回错误代码401(未经授权)。 这是我的测试课 我的资源服务器配置: 如果你想看看整个项目,你可以在这里找到。我已经尝试了不同的测试运行程序和教程中描述的所有内容,但我找不到一个解决方案,如何在测试期间

  • 我的代码:GoogleCredential凭据 credential.refreshToken() 错误日志: 创建服务号的步骤: 我在凭据中的oauth 2.0中创建了一个Web应用程序 然后我用客户端ID创建了一个服务号 现在我正在使用这个服务号和从它生成的p12证书来验证和创建Google凭据的对象 一旦刷新令牌,我就给了我401例外。 在这种情况下,任何帮助都会受到感激

  • 我们正在使用AWS Lambda授权器和API网关来保护我们的下游API。 下面是我们基于Java的lambda授权程序的代码片段 我们需要401(“未经授权”)作为一个回应,有人能请帮助如何做这一点吗?我们有用Java编写的lambda授权器。

  • 我按照这里的教程尝试开始使用spring OAuth。但是,没有页面返回未经授权的401,即使我没有通过服务器验证(本教程中的配置示例应该禁用匿名访问。本教程中与此问题相关的唯一注释只有一个响应,即授权尚未启用,但我在其中一个配置类上有。 所有配置类 应用: “安全”: 可能不相关,但也有: 在通读了教程的完整源代码后,我添加了 最后,这个项目的,因为我在使用Spring时经常遇到特定版本依赖关系