无法在路线中授权,@nestjs/swagger@5.0.9
因为我以t know how to configure the
正确的方式使用 Document`,并且在授权官方文档/stackoverflow/github 中找不到可行的答案。
我偶然发现了 JWT 授权的问题。我正在使用"@nestjs/swagger": "^5.0.9"
,在从公共路由获取访问令牌后,我将其插入到使用.addBearerAuth()
方法配置的 swagger ui 字段“Authorize”中,在此版本(5.0.9)中具有此签名
addBearerAuth(options?: SecuritySchemeObject, name?: string)
Run Code Online (Sandbox Code Playgroud)
与较低版本相反。
我已经在 Postman 中测试了我的 API,并且很容易获得授权,我还创建了一个交集,它在路由调用之前打印标头,但不幸的是它只在我调用公共路由时打印它们:/
我只知道邮递员正在设置一个不记名令牌,并且它会抛出路线,并且 swagger 没有发生类似的情况。
我已经尝试了很多这种配置的组合,但我还没有找到一个解决方案,结果我在我的路由方法中获得了授权,从 swagger 我无法访问它,因为 swagger 身份验证不是设置授权标头,以防配置错误或我做了完全错误的事情。我无法弄清楚。
a的配置addBearerAuth
放在下面:
// swagger config
...
const config = new DocumentBuilder()
.setTitle('SWAGGER API')
.setVersion('1.0.0')
.addBearerAuth(
{
// I was also testing it without prefix 'Bearer ' before the JWT
description: `[just text field] Please enter …
Run Code Online (Sandbox Code Playgroud) 我已经开始学习Nestjs、express和graphql。我在尝试授权使用 jwt 令牌进行身份验证的用户访问时遇到问题。我按照Nestjs 网站上的身份验证教程进行操作。我能够获取当前用户,但是当我尝试实现基本角色基础访问控制时,我无法在 canActivate 方法中访问当前用户。我认为这是因为 Roles Guard 在 Graphql Guard 之前执行。
我将在这里发布代码
gql-auth.guard.ts
import { ExecutionContext } from "@nestjs/common";
import { GqlExecutionContext } from "@nestjs/graphql";
import { AuthGuard } from "@nestjs/passport";
export class GqlAuthGuard extends AuthGuard("jwt") {
getRequest(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
console.log("gql simple context: ", context);
console.log("gqlContext: ", ctx.getContext());
return ctx.getContext().req;
}
}
Run Code Online (Sandbox Code Playgroud)
角色.guard.ts
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { GqlExecutionContext } …
Run Code Online (Sandbox Code Playgroud) 我喜欢实施多个名为 Passport-JWT 的策略,每个策略都有自己的secret
. 有什么办法可以实现吗?据我从文档中了解到,在模块初始化期间只能注册一个秘密:
@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
],
providers: [AuthService, LocalStrategy],
exports: [AuthService, JwtModule],
})
Run Code Online (Sandbox Code Playgroud) 我有一个关于设置环境变量的问题。
在官方文档中,它说在这种情况下使用ConfigModule,但我的情况是一个例外情况。
因为我想在构造函数的 super() 中使用它。
我的代码如下。
这种情况有什么解决办法吗?
如果您需要更多信息,请告诉我。
谢谢大家的支持!!
// jwt.strategy.ts
import { UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm';
import { Strategy, ExtractJwt } from 'passport-jwt';
import { JwtPayload } from './jwt-payload.interface';
import { UserRepository } from './user.repository';
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
@InjectRepository(UserRepository)
private userRepository: UserRepository,
private configService: ConfigService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: configService.get('JWT_TOKEN'),
});
}
async validate(payload: JwtPayload) …
Run Code Online (Sandbox Code Playgroud) 有谁知道我在哪里可以看到 AuthGuard('jwt') 中 canActivate 方法的完整代码?我意识到 canActivate 方法通过使用 console.log() 调用 JwtStrategy 验证方法,如下所示:
// jwt.strategy.ts
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly configService: ConfigService,
private readonly usersService: UsersService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: true,
secretOrKey: configService.get<string>('JWT_SECRET'),
});
}
async validate(payload: any) {
try {
const user = await this.usersService.getUserById(payload.id);
// console.log is here
console.log(user);
return user;
} catch (e) {
console.log(e);
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我使用原始的 canActivate 方法,则会调用 console.log 。我认为 JwtStrategy 是一个中间件,因此只要有请求就会调用 validate 方法。但是,当我尝试重写 canActivate 方法来添加授权时,不会调用 JwtStrategy …
我想实现一个分布式身份验证库以在多个项目中使用它。该库应实现 JWT 身份验证方法。代码如下:
jwt.strategy.ts
import {ExtractJwt, Strategy} from 'passport-jwt';
import {PassportStrategy} from '@nestjs/passport';
import {Injectable} from '@nestjs/common';
import {JwtPayload, User} from './interfaces';
import {ConfigService} from "./config.service";
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(private readonly configService: ConfigService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: configService.get('secretOrPrivateKey'),
});
}
async validate(payload: JwtPayload): Promise<User> {
return {
uuid: payload.uuid,
email: payload.email,
}
}
}
Run Code Online (Sandbox Code Playgroud)
jwt.auth.module.ts:
import {Module, DynamicModule} from '@nestjs/common';
import {JwtModule} from '@nestjs/jwt';
import {JwtStrategy} from './jwt.strategy';
import {PassportModule} from '@nestjs/passport';
import {ConfigService} …
Run Code Online (Sandbox Code Playgroud) 我正在尝试对该控制器进行单元测试并模拟它所需的服务/存储库。
\n@Controller('auth')\nexport class AuthController {\n constructor(\n private readonly authService: AuthService,\n private readonly usersService: UsersService,\n ) {}\n\n @Post('register')\n public async registerAsync(@Body() createUserModel: CreateUserModel) {\n const result = await this.authenticationService.registerUserAsync(createUserModel);\n\n // more code here\n }\n\n @Post('login')\n public async loginAsync(@Body() login: LoginModel): Promise<{ accessToken: string }> {\n const user = await this.usersService.getUserByUsernameAsync(login.username);\n\n // more code here\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n这是我的单元测试文件:
\ndescribe('AuthController', () => {\n let authController: AuthController;\n let authService: AuthService;\n\n beforeEach(async () => {\n const moduleRef: TestingModule = await Test.createTestingModule({\n imports: [JwtModule],\n …
Run Code Online (Sandbox Code Playgroud) 我有一个使用自定义拦截器的控制器:
控制器:
@UseInterceptors(SignInterceptor)
@Get('users')
async findOne(@Query() getUserDto: GetUser) {
return await this.userService.findByUsername(getUserDto.username)
}
Run Code Online (Sandbox Code Playgroud)
我还有 SignService,它是 NestJwt 的包装器:
签到服务模块:
@Module({
imports: [
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
privateKey: configService.get('PRIVATE_KEY'),
publicKey: configService.get('PUBLIC_KEY'),
signOptions: {
expiresIn: configService.get('JWT_EXP_TIME_IN_SECONDS'),
algorithm: 'RS256',
},
}),
inject: [ConfigService],
}),
],
providers: [SignService],
exports: [SignService],
})
export class SignModule {}
Run Code Online (Sandbox Code Playgroud)
最后是 SignInterceptor:
@Injectable()
export class SignInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(map(data => this.sign(data)))
}
sign(data) {
const signed = …
Run Code Online (Sandbox Code Playgroud) 在 Nestjs 中,我通过创建有效负载对象并对其进行签名来创建 JWT(令牌)。像这样的东西:
const jwtPayload: JwtPayload =
{
iss: issuer,
sub: info,
aud: audience,
// exp: - populated by fn: this.jwtService.sign(payload),
// iat: - populated by fn: this.jwtService.sign(payload),
jti: 'XXXX1234'
}
const signedJwtAccessToken: string = this.jwtService.sign(jwtPayload);
Run Code Online (Sandbox Code Playgroud)
Nest 将 jwtPayload 编码为字符串。
对于清理工作,我想知道 JWT 何时到期。这会通过 .sign() 函数自动编码到“ signedJwtAccessToken ”(属性.exp )中。
要在签名后立即访问它,需要对其进行解码。
在签署后立即以相同的方法解码签名的JwtAccessToken最简单的方法是什么???
笔记:
当 JWT 从客户端返回时,nestjs 在访问 fn: validate() 时对其进行解码,但我想在签名后立即解码 - 在将响应发送给客户端之前,如下所示:
// signing - encoding
const signedJwtAccessToken: string = this.jwtService.sign(jwtPayload);
// decoding
const decodedJwtAccessToken: string = decodeJwt(signedJwtAccessToken); …
Run Code Online (Sandbox Code Playgroud) 我已经在 nestJs 中实现了 jwt 身份验证。但是,每当我尝试使用以下授权标头进行身份验证时:
Bearer <token> or JWT <token>
Run Code Online (Sandbox Code Playgroud)
我得到了 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(); …
Run Code Online (Sandbox Code Playgroud) nestjs ×10
nestjs-jwt ×10
jwt ×4
passport-jwt ×2
passport.js ×2
graphql ×1
javascript ×1
jestjs ×1
swagger ×1
typeorm ×1
typescript ×1