nestjs 中的可选身份验证

Posted

技术标签:

【中文标题】nestjs 中的可选身份验证【英文标题】:Optional Authentication in nestjs 【发布时间】:2019-04-14 10:39:48 【问题描述】:

我想知道是否存在使req.user 对象在控制器方法中可用的装饰器,如果用户已登录(发送了授权标头),如果没有,则让req.user 为空。

如果用户未登录,AuthGuard 装饰器将返回 401,因此不适合我的情况。

【问题讨论】:

如果您还没有,请查看:docs.nestjs.com/techniques/authentication 【参考方案1】:

没有内置的装饰器,但您可以轻松地自己创建一个。请参阅docs 中的示例:

import  createParamDecorator  from '@nestjs/common';
import  AuthGuard  from '@nestjs/passport';

export const User = createParamDecorator((data, req) => 
  return req.user;
);

由于内置的​​AuthGuard抛出异常,你可以创建自己的版本并覆盖请求处理程序:

@Injectable()
export class MyAuthGuard extends AuthGuard('jwt') 

  handleRequest(err, user, info) 
    // no error is thrown if no user is found
    // You can use info for logging (e.g. token is expired etc.)
    // e.g.: if (info instanceof TokenExpiredError) ...
    return user;
  


确保您没有在JwtStrategy 中抛出错误:

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) 
  constructor(private readonly authService: AuthService) 
    super(
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: 'secretKey',
    );
  

  async validate(payload) 
    const user = await this.authService.validateUser(payload);
    // in the docs an error is thrown if no user is found
    return user;
  

然后你可以像这样在Controller 中使用它:

@Get()
@UseGuards(MyAuthGuard)
getUser(@User() user) 
  return user;

【讨论】:

完美答案。在***和github上找不到它。 我找不到@User 装饰器 @jeromerg 这是一个自定义装饰器,在此答案的第一个代码 sn-p 中定义。【参考方案2】:

另一种方法是创建匿名护照策略:

// In anonymous.strategy.ts
@Injectable()
export class AnonymousStrategy extends PassportStrategy(Strategy, 'anonymous') 
  constructor() 
    super()
  

  authenticate() 
    return this.success()
  

然后,在控制器中链接这个策略:

// In create-post.controller.ts
@Controller()
export class CreatePostController 
  @UseGuards(AuthGuard(['jwt', 'anonymous'])) // first success wins
  @Post('/posts')
  async createPost(@Req() req: Request, @Body() dto: CreatePostDto) 
    const user = req.user as ExpressUser

    if (user.email) 
      // Do something if user is authenticated
     else 
      // Do something if user is not authenticated
    
    ...
  

【讨论】:

谢谢,我觉得用这个比较灵活。因为有时我们需要拒绝未经身份验证的用户。 我用我的 Graphql Guard ``` import Injectable, ExecutionContext from '@nestjs/common' import AuthGuard from '@nestjs/passport' import GqlExecutionContext from '@nestjs /graphql' @Injectable() 导出类 EveryoneGqlAuthGuard 扩展 AuthGuard(['jwt', 'anonymous']) getRequest(context: ExecutionContext) const ctx = GqlExecutionContext.create(context) return ctx.getContext().req ```

以上是关于nestjs 中的可选身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Passport.js 可选身份验证

使用电子邮件进行身份验证时,NestJS 护照身份验证返回 401

NestJs JWT 身份验证返回 401

Nestjs 身份验证

NestJS jwt-passport 身份验证

NestJs 使用 jwt 和私钥和公钥进行身份验证