在身份验证/授权过程中,我很难弄清楚 NestJS 和 PassportJS 的组合,而且我是一种在开发时不喜欢魔法的开发人员。
基本上,我的目标是了解 AuthGuard 如何知道项目中正在实施的 Passport 策略,它可以是本地策略,也可以是任何其他策略,例如 JWT 策略。我有两个模块 AuthModule 和 UserModule,这就是 AuthService 的样子:
@Injectable()
export class AuthService {
constructor(private usersService: UsersService){}
async validateUser(username: string, password: string): Promise<any> {
const user = await this.usersService.findOne(username);
if (user && user.password === password) {
const {password, ...result} = user
return result
}
return null
}
}
用户服务:
import { Injectable } from '@nestjs/common';
export type User = any;
@Injectable()
export class UsersService {
private readonly users = [
{
userId: 1,
username: 'John Marston',
password: 'rdr1',
},
{
userId: 2,
username: 'Arthur Morgan',
password: 'rdr2',
},
]
async findOne(username: string): Promise<User | undefined> {
return this.users.find(user => user.username === username)
}
}
安装 Passport 和 NestJS 的软件包后,我导入了 PassportModule 并实现了 LocalStrategy 并将该策略作为提供者导入到 AuthModule
中本地策略:
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private 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;
}
}
@Module({
imports: [UsersModule, PassportModule],
providers: [AuthService, LocalStrategy]
})
export class AuthModule {}
import { Controller, Post, Request, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Controller()
export class AppController {
@UseGuards(AuthGuard('local'))
@Post('login')
async login(@Request() req) {
return req.user;
}
}
直到这部分我都明白了。我也明白我们如何获取 req.user 对象等,但我不明白 AuthGuard 如何知道我们实施了 Passport 本地策略。它是否会查看文件(抱歉,如果这么说很愚蠢)并找到我们导入 PassportModule 的位置以及我们实现 LocalStrategy 的位置,因为该类扩展了 PassportStrategy 类,但同样重要的是,从护照导入-本地。
我确实明白 AuthGuard 是一种特殊类型的 Guard,但我不确定我是否理解正确。
我有一篇关于此的相当不错的文章,但也将其放在 StackOverflow 上:
Strategy
包中的每个
passport-*
都有一个
name
属性,它是策略的名称。对于
passport-local
,
name
是
local
。对于
passport-jwt
,该名称为
'jwt'
。这并不总是一一对应,但每个包裹都应记录其护照名称。这是传递给
passport.use()
和
passport.authenticate()
的名称。
passport.use
是通过
PassportStrategy
的
@nestjs/passport
类中的一些巧妙代码调用的,以将策略注册到护照上,并且
passport.authenticate
是在
AuthGuard()
内部调用的,使用通过护照模块选项设置的全局默认值或通过mixin 的参数,如代码示例中的
local
。