【问题标题】:NestJs JWT Authentication returns 401NestJs JWT 身份验证返回 401
【发布时间】:2019-09-13 04:37:02
【问题描述】:

我已经在 nestJs 中实现了 jwt 身份验证。但是,每当我尝试使用以下授权标头进行身份验证时:

Bearer <token> or JWT <token>

我得到了 401。这些是我的身份验证文件

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
  constructor(private readonly authService: AuthService) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: `${process.env.SECRET}`,
    });
  }

  async validate(payload: Credentials) {
    const user: Account = await this.authService.validateAccount(payload);
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}


@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  canActivate(context: ExecutionContext) {
    return super.canActivate(context);
  }

  handleRequest(err, user, info) {
    if (err || !user) {
      throw err || new UnauthorizedException();
    }
    return user;
  }
}

这是我的身份验证模块

@Module({
  imports: [
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.register({
      secretOrPrivateKey: `${process.env.SECRET}`,
    }),
    AccountModule,
  ],
  providers: [AuthService, JwtStrategy],
  controllers: [AuthController],
  exports: [PassportModule, AuthService],
})
export class AuthModule {

}

【问题讨论】:

  • 您能在authService.validateAccount 中添加console.log 吗?它被称为?它是否返回一个真实的值?
  • 令我惊讶的是它没有被调用。
  • @Arsene 这对你有用吗,我遇到了同样的问题,registerAsync 由于某种原因不起作用。但是 register 方法有效

标签: typescript jwt nestjs nestjs-passport nestjs-jwt


【解决方案1】:

validate 只会在您传递有效的 jwt 令牌时被调用。当令牌使用不同的秘密签名或过期时,validate 将永远不会被调用。确保您拥有有效的令牌。例如,您可以使用jwt debugger 检查您的令牌。

【讨论】:

  • 令牌有效。但是我仍然收到 401。我怎么知道 Nestjs 管道中的问题在哪里?
  • 您已经扩展了AuthGuard,因此您可以将console.log 语句添加到它的方法中。您还可以在库代码中设置断点并进行调试。
  • 由于您似乎使用的几乎都是标准设置,我不这么认为,不。正如您所说,您的令牌没有过期并且使用正确的秘密签名,它仍然可能是错误的标头格式,版本冲突,......
  • 您好 NestJs 极客,请帮我解决这个问题。我已经和这个斗争了一段时间了。没有解决方案。
  • 您必须提供更多信息,例如日志等或在codesandbox.io上创建可重现的版本
【解决方案2】:

我遇到了类似的问题,nestjs 护照 jwt 模块在我的本地机器上运行良好,但在实时服务器上无法运行。经过半天的研究,我发现我的令牌头没有到达实时服务器,原因是我在实时服务器上使用了 nginx(proxy_pass)并且我的头字段名称是“access_token”所以出于某种原因 nginx 删除了它.

制作一个简单的全局中间件并检查您是否在标头中接收到令牌。

希望对某人有所帮助。

【讨论】:

    【解决方案3】:

    我遇到了同样的问题。这是我的代码(工作)供您比较:

    src/auth/auth.module.ts

    import { Module } from '@nestjs/common';
    import { JwtModule } from '@nestjs/jwt';
    import { AuthService } from './auth.service';
    import { JwtStrategy } from './jwt.strategy';
    import { UserModule } from 'src/user/user.module';
    import { PassportModule } from '@nestjs/passport';
    
    @Module({
      imports: [
        PassportModule.register({ defaultStrategy: 'jwt' }),
        JwtModule.register({
          secretOrPrivateKey: 'secretKey',
          signOptions: {
            expiresIn: '1d',
          },
        }),
        UserModule,
      ],
      providers: [AuthService, JwtStrategy],
      exports: [PassportModule, AuthService],
    })
    export class AuthModule {}
    

    src/auth/auth.service.ts

    import { Injectable } from '@nestjs/common';
    import { JwtService } from '@nestjs/jwt';
    import { JwtPayload } from './interfaces/jwt-payload.interface';
    import { UserService } from 'src/user/user.service';
    
    @Injectable()
    export class AuthService {
      constructor(
        private readonly jwtService: JwtService,
        private readonly userService: UserService,
      ) {}
    
      makeToken(payload: JwtPayload) {
        const { email } = payload;
        return this.jwtService.sign({ email });
      }
    
      checkToken(token: string) {
        return this.jwtService.verify(token);
      }
    
      async validateUser(payload: JwtPayload) {
        return await this.userService.read(payload.email);
      }
    }
    

    src/auth/jwt.strategy.ts

    import { Strategy, ExtractJwt, VerifiedCallback } from 'passport-jwt';
    import { AuthService } from './auth.service';
    import { PassportStrategy } from '@nestjs/passport';
    import { Injectable, UnauthorizedException } from '@nestjs/common';
    import { JwtPayload } from './interfaces/jwt-payload.interface';
    
    @Injectable()
    export class JwtStrategy extends PassportStrategy(Strategy) {
      constructor(private readonly authService: AuthService) {
        super({
          jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
          secretOrKey: 'secretKey',
        });
      }
    
      async validate(payload: JwtPayload, done: VerifiedCallback) {
        const user = await this.authService.validateUser(payload);
        if (!user) {
          done(new UnauthorizedException(), false);
        }
        return done(null, user);
      }
    }
    

    src/auth/interfaces/jwt-payload.interface.ts

    export interface JwtPayload {
      email: string;
    }
    

    src/account/account.module.ts

    import { Module } from '@nestjs/common';
    import { AccountController } from './account.controller';
    import { PassportModule } from '@nestjs/passport';
    import { AuthModule } from 'src/auth/auth.module';
    
    @Module({
      imports: [AuthModule],
      controllers: [AccountController],
    })
    export class AccountModule {}
    

    src/account/account.controller.ts

    import { Controller, UseGuards, Post } from '@nestjs/common';
    import { AuthGuard } from '@nestjs/passport';
    
    @Controller('account')
    export class AccountController {
      @Post('skills')
      @UseGuards(AuthGuard())
      updateSkills() {
        return console.log('something');
      }
    }
    

    P.S.:我没有做 JwtAuthGuard。

    希望对你有所帮助:)

    【讨论】:

    • 我不确定发生了什么,但它不起作用。
    【解决方案4】:

    您可以查看带有护照和 NestJS 的最小工作示例

    https://github.com/leosuncin/nest-auth-example

    与您的代码的主要区别:

    @Module({
      imports: [
        PassportModule.register({ defaultStrategy: 'jwt' }), // I don't do this because I explicity call every stratategy
        JwtModule.register({
          secretOrPrivateKey: 'secretKey',
          signOptions: {
            expiresIn: '1d',
          },
        }),
        UserModule,
      ],
      providers: [AuthService, JwtStrategy],
      exports: [PassportModule, AuthService], // I don't do this
    })
    

    我不使用任何JwtAuthGuard,只使用默认的。

    【讨论】:

      【解决方案5】:

      我遇到了这个问题,我解决了。 只需删除 ${procces.env.JWT_SECRET} 并执行其他操作,例如异步注册,我不知道为什么,但它可以工作。

      【讨论】:

        猜你喜欢
        • 2019-03-28
        • 1970-01-01
        • 1970-01-01
        • 2020-07-18
        • 2021-10-14
        • 2021-03-02
        • 1970-01-01
        • 2018-12-09
        • 2017-06-12
        相关资源
        最近更新 更多