繁体   English   中英

在 Nest.js 中使用本地护照的 failureRedirect 选项

[英]Using failureRedirect option of passport-local with Nest.js

在使用 Nest.js 进行身份验证后,我需要帮助进行处理

没有 Nest.js

app.post('/login', passport.authenticate('local', {
    //Passing options here.
    successRedirect: '/',
    failureRedirect: '/login'
}));

我的代码是。 (使用 Nest.js)

本地策略.ts

import { Injectable, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { Strategy } from "passport-local";
import { AuthService } from "./auth.service";

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
    constructor(private authService: AuthService) {
        super({
            //I tried passing the option here. but failed.
        })
    }

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

local.guard.ts

import { Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";

@Injectable
export class LocalAuthGuard extends AuthGuard('local') {}

auth.controller.ts

import { Controller, Get, Post, Render, UseGuards } from "@nestjs/common";
import { LocalAuthGuard } from "./local.guard";

@Controller()
export class AuthController {
    @Get("/login")
    @Render("login")
    getLogin() {}
    
    //Redirect to '/login' when authentication failed.
    @UseGuards(LocalAuthGuard)
    @Post("/login")
    postLogin() {}
}

auth.module.ts

import { Module } from "@nestjs/common";
import { PassportModule } from "@nestjs/passport";
import { AuthController } from "./auth.controller";
import { AuthService } from "./auth.service";
import { LocalStrategy } from "./local.strategy";
import { LocalAuthGuard } from "./local.guard";

@Module({
   controllers: [AuthController],
   imports: [PassportModule],
   providers: [AuthService, LocalStrategy, LocalAuthGuard]
})
export class AuthModule {}

我尝试将代码添加到AuthController#postLogin以在登录失败时重定向,但代码似乎仅在成功登录时运行。 如果使用passport-local的failureRedirect选项登录失败,我想再次重定向到登录页面。

我找到了一种解决方法,因为遗憾的是使用护照选项不起作用:

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
  getAuthenticateOptions(context: ExecutionContext): IAuthModuleOptions {
    return {
      successReturnToOrRedirect: '/',
      failureRedirect: '/login',
    };
  }
}

相反,我创建了一个 Nestjs 过滤器来捕获包含重定向 URL 的异常。

重定向.exception.ts

export class RedirectingException {
  constructor(public url: string) {}
}

重定向异常.filter.ts

import { ArgumentsHost, Catch, ExceptionFilter } from '@nestjs/common';
import { Response } from 'express';
import { RedirectingException } from './redirecting.exception';

@Catch(RedirectingException)
export class RedirectingExceptionFilter implements ExceptionFilter {
  catch(exception: RedirectingException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    response.redirect(exception.url);
  }
}

在我的验证方法中,我使用正确的错误消息抛出 RedirectingException,例如

throw new RedirectingException('/login?error="User not found"');

而 controller 处理了重定向的 rest 并将错误传递给视图,因此可以显示:

@Get('/login')
@Render('login.pug')
@Public()
async login(@Query() query) {
  return { error: query.error };
}

@Post('/login')
@Public()
@UseGuards(LocalAuthGuard)
@Redirect('/')
async doLogin() {}

我宁愿使用包括 failureFlash 在内的护照功能,但我无法让它工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM