nestjs守卫/全局守卫校验jwt

news2024/11/23 12:32:24

一、守卫

目标

部分接口需要用户登录后才可以访问,用户登录后可以颁发 jwt_token 给前端,前端在调用需要鉴权的接口,需要在请求头添加 jwt_token,后端校验通过才能继续访问,否则返回403无权访问

创建守卫 anth

安装依赖
npm i @nestjs/jwt -S
配置 jwt 常量参数 constants/index.ts
// jwt秘钥,固定随机字符串
export const JWT_SECRET = "NODE_TEST_SECRET";

// jwt有效期 Eg: "60s", "3h", "2d"
export const JWT_EXPIRES = "2h"; // 2小时
创建 auth 模块 auth/auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { JWT_SECRET, JWT_EXPIRES } from '../constants';

@Module({
  imports: [
    JwtModule.register({
      secret: JWT_SECRET, // jwt秘钥
      signOptions: {
        expiresIn: JWT_EXPIRES, // jwt有效期
      }
    })
  ],
  providers: [AuthService],
  exports: [AuthService]
})
export class AuthModule {}
创建 auth 服务 auth/auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(private readonly jwtService: JwtService) {}

  // 创建jwt_token
  async createToken(userInfo) {
    // 将用户信息(userId、name)存放到 jwt 中
    return {
      access_token: this.jwtService.sign(userInfo)
    };
  }

  // 校验登录状态
  validateToken(token) {
    if (!token) {
      return false;
    }
    try {
      return this.jwtService.verify(token);
    } catch {
      return false;
    }
  }
}
创建 auth 守卫 auth/auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private authService: AuthService) {}

  canActivate(context: ExecutionContext) {
    const request = context.switchToHttp().getRequest();
    const token = request.headers['authorization']; // 从请求头中获取 token
    if (!token) {
      return false;
    } else {
      return this.authService.validateToken(token); // 如果 token 有效,返回 true,允许访问资源
    }
  }
}

使用守卫 auth

需要鉴权的模块添加 auth 模块

api.module.ts

...
import { AuthModule } from '../auth/auth.module';

@Module({
  imports: [AuthModule],
  ...
})
export class ApiModule {}
需要鉴权的接口引入守卫

api.controller.ts

...
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from '../auth/auth.guard';

@Controller('api')
export class ApiController {
  constructor(private readonly apiService: ApiService) {}

  @Get('getUserInfo')
  @UseGuards(AuthGuard) // 需要鉴权的接口添加UseGuards
  getUserInfo(): any {
    return this.apiService.getUserInfo();
  }
}
登录

调用 auth/auth.service.ts 中的 createToken 生成 jwt_token 返回给前端

前端在请求头添加 authorization

如果请求头没有 authorization,或者 authorization 失效,则返回 403 Forbidden

二、全局守卫

目标

由于单个守卫需要引入守卫模块、守卫方法,并且针对每一个接口加 @UseGuards 装饰器,使用起来比较繁琐。项目中经常遇到非常多的接口都需要鉴权,所以就需要使用全局守卫来校验需要鉴权的接口。

注意:获取与解析 jwt_token 的方法上面守卫的方法一致,auth/auth.service,此处不再赘述。

创建全局守卫

配置需要鉴权的接口常量 constants/index.ts
// 需要校验 jwt 的 url 列表
export const ValidUrlList = [
  '/api/getUserInfo',
  '/api/product/buy',
  '/api/queryUserWallet'
];
新建全局守卫 global.guard.ts
import { Injectable, NestInterceptor, ExecutionContext, HttpException, HttpStatus } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AuthService } from './auth/auth.service';
import { ValidUrlList } from './constants';

@Injectable()
export class GlobalGuard implements NestInterceptor {
  constructor(private authService: AuthService) {}
  intercept(context: ExecutionContext, next): Observable<any> {
    // 在这里执行全局守卫逻辑
    const request = context.switchToHttp().getRequest();
    // 从请求头中获取 token
    const token = request.headers['authorization'];
    // 请求的url,用于判断是否需要校验jwt
    const url = request.url;
    if (ValidUrlList.includes(url)) {
      // 需要鉴权才能访问的接口
      const validRes = this.authService.validateToken(token);
      if (!validRes) {
        return next.handle().pipe(map(() => {
          // 如果没有提供令牌,返回错误响应或执行其他逻辑
          return new HttpException('Forbidden', HttpStatus.FORBIDDEN);
        }));
      }
    }
    // 不需要校验的接口、校验通过的接口直接放行
    return next.handle();
  }
}

在 app.module.ts 配置全局守卫

// ...
import { APP_INTERCEPTOR } from '@nestjs/core';
import { JwtModule } from '@nestjs/jwt';
import { GlobalGuard } from './global.guard';
import { JWT_SECRET, JWT_EXPIRES } from './constants';
import { AuthService } from './auth/auth.service';

@Module({
  imports: [
    JwtModule.register({
      secret: JWT_SECRET, // jwt秘钥
      signOptions: {
        expiresIn: JWT_EXPIRES, // jwt有效期
      }
    }),
  ],
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: GlobalGuard,
    },
    AuthService
  ],
})
export class AppModule {}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1308803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【期末复习向】常见的激活函数

激活函数是非线性的函数&#xff0c;使用它的原因就是因为线性函数无论叠加多少层&#xff0c;最终带来的变化都是线性的组合&#xff0c;一般也只能用于线性分类&#xff0c;如经典的多层感知机。但是如果加上非线性的变换&#xff0c;根据通用近似定理&#xff0c;就可使得神…

python+pytest接口自动化(15)-日志管理模块loguru简介

python自带日志管理模块logging&#xff0c;使用时可进行模块化配置&#xff0c; 但logging配置起来比较繁琐&#xff0c;且在多进行多线程等场景下使用时&#xff0c;如果不经过特殊处理&#xff0c;则容易出现日志丢失或记录错乱的情况。 python中有一个用起来非常简便的第…

鸿蒙开发组件之DatePicker

一、功能 DatePicker是鸿蒙开发中的日期组件&#xff0c;主要用来日期的选择。样式如下 二、初始化一个DatePicker DatePicker({start:new Date(1970-01-01),end: new Date(2035-12-31)})当然我们的start和end参数是可选的&#xff0c;不必须传递&#xff0c;所以初始化也可以…

【动态规划】06路径问题_不同路径II_C++(medium)

题目链接&#xff1a;leetcode不同路径II 目录 题目解析&#xff1a; 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目解析&#xff1a; 题目让我们求在考虑网格中有障碍物的情况下&#xff0c;从左上角到右下角将会有多少条不同的路径…

【ARM Trace32(劳特巴赫) 使用介绍 14 -- Go.direct 介绍】

请阅读【Trace32 ARM 专栏导读】 文章目录 Trace32 Go.directGo配合程序断点使用Go 配合读写断点使用Go 快速回到上一层函数 System.Mode Go Trace32 Go.direct TRACE32调试过程中&#xff0c;会经常对芯片/内核进行控制&#xff0c;比如全速运行、暂停、单步等等。这篇文章先…

出现 Error:Unable to access jarfile xxxx\target\nacos-server.jar 解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 执行Nacos中的startup.cmd的时候出现闪退,于是在该脚本的最后一行添加pause,查看因为什么原因闪退 出现的bug如下所示:Error:Unable to access jarfile xxxx\target\nacos-server.jar 截图如下所示: 查看内部文件夹,…

德语 Alt 代码表

德语的 Alt 代码表&#xff0c;请参考下图。 输入方法就是按住 Alt 键不松开&#xff0c;然后在小键盘上输入字符&#xff0c;松开 Alt 键&#xff0c;计算机就能输出上面的字符了。 德语 Alt 代码表 - 系统容器 - iSharkFly德语的 Alt 代码表&#xff0c;请参考下图。 输入方…

c语言为什么要引入数据类型

大家好&#xff0c;今天给大家介绍c语言为什么要引入数据类型&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 在本人看来,C语言引入数据类型的原因主要有以下几点&#xff1a; 数…

消息中间件比较

那都有哪些中间件可供选择呢。其实现在主流的消息中间件就4种&#xff1a;kafka、ActiveMQ、RocketMQ、RabbitMQ 下面我们来看一下&#xff0c;他们之间有什么区别&#xff0c;他们分别应该用于什么场景 ActiveMQ 我们先看ActiveMQ。其实一般早些的项目需要引入消息中间件&…

集群监控Zabbix和Prometheus

文章目录 一、Zabbix入门概述1、Zabbix概述2、Zabbix 基础架构3、Zabbix部署3.1 前提环境准备3.2 安装Zabbix3.3 配置Zabbix3.4 启动停止Zabbix 二、Zabbix的使用与集成1、Zabbix常用术语2、Zabbix实战2.1 创建Host2.2 创建监控项&#xff08;Items&#xff09;2.3 创建触发器&…

寻找最大整数 C语言xdoj51

问题描述 从键盘输入四个整数&#xff0c;找出其中的最大值并将其输出。 输入说明 输入4个整数&#xff0c;用空格分隔 输出说明 输出值最大的一个整数 输入样例 25 99 -46 0 输出样例 99 #include <stdio.h>//寻找最大整数 int main() {int i, a[4]…

5 转向事件驱动的架构

文章目录 核心概念消息代理事件和消息了解事件异步消息通信响应式系统 事件驱动的利弊消息传递模式发布—订阅工作队列过滤器数据持久性 消息传递代理协议、标准和工具AMQP和RabbitMQ基本概念交换类型和路由消息确认和拒绝 设置RabbitMQ安装RabbitMQRabbitMQ管理界面 Spring AM…

Unity_FairyGUI发布导入Unity编辑器资源报错

Unity_FairyGUI发布导入Unity编辑器资源报错 报错&#xff1a; FairyGUI: settings for Assets/UI/XMUI/XMSubway_atlas0.png is wrong! Correct values are: (Generate Mip Mapsunchecked) UnityEngine.Debug:LogWarning (object) FairyGUI.UIPackage:LoadAtlas (FairyGUI.P…

用Go汇编实现一个快速排序算法

本代码全网首发&#xff0c;使用Go plan9 windows arm64汇编&#xff0c;实现基础版快速排序算法。 未引入随机因子的快速排序的普通Go代码长这样。 func QuickSort(arr []int) {if len(arr) < 1 {return}base, l, r : arr[0], 0, len(arr)-1for i : 1; i < r; {if arr…

UI设计中的2.5D插画是什么?

2.5d插画&#xff0c;你可能第一时间会想2D应该是平面的&#xff0c;3D是立体的&#xff0c;介于2D和3D之间&#xff0c;那么它就是在平面上面看立体的2.5D透视原理图像&#xff0c;就是物体的正面、光面和暗面三面组成&#xff0c;也算是伪3D。 首先&#xff0c;设计师需要设…

一进一出两线制(三线制)模拟量高速信号(50KHz)隔离变送器

一进一出两线制(三线制)模拟量高速信号(50KHz)隔离变送器 型号&#xff1a;JSD TA-2311F系列 产品特点&#xff1a; ◆小体积,低成本,标准 DIN35mm 导轨安装方式 ◆三端隔离(输入、输出、工作电源间相互隔离) ◆高速信号采集,隔离等(-3dB,Min≤ 3.5 uS) ◆高精度等级(0.1% F.S&…

Leetcode 2132. 用邮票贴满网格图(Java + 两次一维前缀和 + 二维差分)

Leetcode 2132. 用邮票贴满网格图&#xff08;Java 两次一维前缀和 二维差分&#xff09; 题目 给你一个 m x n 的二进制矩阵 grid &#xff0c;每个格子要么为 0 &#xff08;空&#xff09;要么为 1 &#xff08;被占据&#xff09;。给你邮票的尺寸为 stampHeight x sta…

2-2基础算法-递归/进制转换

文章目录 一.递归二.进制转换 一.递归 1.数的计算 评测系统 #include <iostream> int countCombinations(int n) { //计算当然组合种数if (n 1) {return 1;}int count 1;//数字本身就是一个有效组合for (int i 1; i < n / 2; i) {count countCombinations(i);/…

50mA、24V、超低 IQ、低压降稳压器

一、Description The TPS715 low-dropout (LDO) voltage regulators offer the benefits of high input voltage, low-dropout voltage, low-power operation, and miniaturized packaging. The devices, which operate over an input range of 2.5 V to 24 V, are stable wit…

【云原生kubernets】Ingress 功能与应用

一、Ingress 介绍 1.1.Ingress产生原因&#xff1a; 当我们使用Service的时候&#xff0c;Service对集群之外暴露服务的主要方式有两种&#xff1a;NotePort和LoadBalancer&#xff0c;但是这两种方式&#xff0c;都有一定的缺点&#xff1a; &#xff08;1&#xff09;Node…