使用JWT Passport进行NestJS身份验证不起作用

问题描述:

我正在尝试使用jwt-passport和nestjs建立一个非常简单的登录系统.我遵循了本教程: https://docs.nestjs.com/techniques/authentication 但我就是无法正常工作.我真的很陌生,如果有人可以向我展示方法,我将不胜感激.

I am trying to set up a very simple login system using jwt-passport with nestjs. I followed this tutorial: https://docs.nestjs.com/techniques/authentication but I just can't get it to work. I am really new to this stuff and would appreciate if anyone can show me the way.

我将登录名发送到服务器的方式:

The way I send the login to the server:

    this.clientAuthService.login(this.userName, this.password).then(response => {
        this.clientAuthService.setToken(response.access_token);
        this.router.navigate(['/backend']);
    });

我的ClientAuthService:

My ClientAuthService:

export class ClientAuthService {

  constructor(private http: HttpClient, @Inject(PLATFORM_ID) private platformId) {
  }

  getToken(): string {
    if (isPlatformBrowser(this.platformId)) {
      return localStorage.getItem(TOKEN_NAME);
    } else {
      return '';
    }
  }

  setToken(token: string): void {
    if (isPlatformBrowser(this.platformId)) {
      localStorage.setItem(TOKEN_NAME, token);
    }
  }

  removeToken() {
    if (isPlatformBrowser(this.platformId)) {
      localStorage.removeItem(TOKEN_NAME);
    }
  }

  getTokenExpirationDate(token: string): Date {
    const decoded = jwt_decode(token);

    if (decoded.exp === undefined) {
      return null;
    }

    const date = new Date(0);
    date.setUTCSeconds(decoded.exp);
    return date;
  }

  isTokenExpired(token?: string): boolean {
    if (!token) {
      token = this.getToken();
    }
    if (!token) {
      return true;
    }

    const date = this.getTokenExpirationDate(token);
    if (date === undefined) {
      return false;
    }
    return !(date.valueOf() > new Date().valueOf());
  }

  login(userName: string, password: string): Promise<any> {
    const loginData = {username: userName, password};
    return this.http
      .post(Constants.hdaApiUrl + 'user/login', loginData, {headers: new HttpHeaders({'Content-Type': 'application/json'})})
      .toPromise();
  }

}

我的user.controller.ts

My user.controller.ts

@Controller('user')
export class UserController {

  constructor(private readonly authService: AuthService) {
  }

  @UseGuards(AuthGuard('local'))
  @Post('login')
  authenticate(@Request() req) {
    return this.authService.login(req);
  }

}

我的user.service.ts

My user.service.ts

export class UsersService {
  private readonly users: User[];

  constructor() {
    this.users = [
      {
        userId: 1,
        username: 'test',
        password: '12345',
      }
    ];
  }

  async findOne(username: string): Promise<User | undefined> {
    return this.users.find(user => user.username === username);
  }
}

然后我有了jwt.strategy.ts

Then I have the jwt.strategy.ts

export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: Constants.jwtSecret,
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}

和local.strategy.ts

and the local.strategy.ts

export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private readonly authService: AuthService) {
    super();
  }

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

大多数情况下,我只是按照本教程进行操作,并且自己为客户端添加了一些内容. 我错过了带有UseGuard('local')的登录路线,但是添加后我总是收到401错误. 当我不使用UseGuard('local')时,在登​​录表单中键入什么都无所谓.提交详细信息后,即使不正确也可以访问后端.

Mostly I just followed the tutorial and added some stuff for the client-side by myself. I missed the part with the UseGuard('local') for the login route but after I added it I am getting 401 error always. When I don't use UseGuard('local') it doesn't matter what I type in the login form. After I submit the details, I get access to the backend even tho it was not correct.

另外,值得一提的是,在WebStorm中jwt.strategy.ts和local.strategy.ts中的validate方法标记为not used.

Also, it might be worth to mention that the validate methods in jwt.strategy.ts and local.strategy.ts are marked as not used in WebStorm.

我在这里知道很多代码,但是我需要帮助,因为找不到最新的NestJS身份验证配置的任何其他来源.感觉就像我遵循的教程对于初学者来说错过了很多步骤.

I know its a lot of code here but I need help because I cannot find any other sources for NestJS auth configuration which is up to date. It feels like the tutorial I followed missed a lot of steps for beginners.

确保您的帖子正文(有效载荷)与validate方法的签名相同(实际上必须是用户名和密码).

Make sure your post body (payload) is identical to the signature of the validate method (it actually has to be username & password).