nest+vue实现加解密及jwt生成、验证,主要nest代码

52 阅读2分钟

nest端使用 “crypto” 插件

实现加解密工具函数

// 加密
export const enCrypt = (info) => {
  if (typeof info === 'object') {
    info = JSON.stringify(info);
  }
  const cipher = createCipheriv(
    'aes-256-cbc',
    Buffer.from(cryptoKey),
    Buffer.from(aesIv),
  );
  const encrypted = cipher.update(info, 'utf8', 'hex') + cipher.final('hex');
  // 十六进制字符串转换为 Buffer
  const buffer = Buffer.from(encrypted, 'hex');

  // 将 Buffer 转换为 Base64 编码的字符串
  const base64String = buffer.toString('base64');
  return base64String;
};

// 解密
export const deCrypt = (info: any) => {
  console.log(info, '加密');

  info = info.replace(/\r\n/g, '');
  if (!isHex(info)) {
    const buffer = Buffer.from(info, 'base64'); // Base64 解码为 Buffer
    info = buffer.toString('hex'); //buffer解析为16进制
  }
  console.log(info, '1');

  const decipher = createDecipheriv(
    'aes-256-cbc',
    Buffer.from(cryptoKey),
    Buffer.from(aesIv),
  );
  console.log(decipher, '2');

  decipher.setAutoPadding(true); // 这将自动移除PKCS#7填充
  console.log(decipher, '3');

  const decrypted =
    decipher.update(info, 'hex', 'utf8') + decipher.final('utf8');
  return decrypted;
};

中间件内实现token鉴权及请求体解密:

仅实现关键代码、并未对各种情况进行处理,未写功能

export class AppMiddleware implements NestMiddleware {
  @Inject(JwtService)
  private jwtService: JwtService;

  use(req: Request, res: Response, next: () => void) {
    // console.log('开始执行中间件aaa...', req.body, req.originalUrl, req.baseUrl);
    const secretData = req.body.data;
    console.log(req.headers.authorization, 'shili');

    const authorization = req.headers.authorization;
    if (authorization) {
      const authorizationRow = authorization.slice(7);
      const data = this.jwtService.verify(authorizationRow);
      console.log(data, 'jwt');
    }

    if (secretData) {
      const deData = deCrypt(secretData);
      console.log('解密:', deData);
      req.body.data = deData;
    }

    next();
    console.log('结束执行中间件aaa...');
  }
}

login接口拿到解密后的前端传输数据,进行相关判断操作(省略)后,返回生成的token

@Injectable()
export class AppService {
  @Inject(JwtService)
  private jwtService: JwtService;

  getHello(): string {
    return 'Hello Wor12321321ld!';
  }

  login(dto): string {
    console.log(dto, 'dto');
    const data = JSON.parse(dto.data);
    const token = this.jwtService.sign({
      userName: data.phone,
    });
    console.log(token, 'zhijie');
    return `bearer ${token}`;
  }
}

拦截器对响应体做加密操作

import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { enCrypt } from 'src/utils/crypt';

@Injectable()
export class CryptoInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next
      .handle()
      .pipe(
        map((data) => ({ code: 200, data: enCrypt(JSON.stringify(data)) })),
      );
  }
}

前端使用对应的插件实现方法即可:一般配置在request.js中用拦截器实现

import CryptoJS from 'crypto-js'
const cryptoKey = 'adjg894kjgng394uadjg894kjgng394u'

const ivStr = 'adjg894kjgng394u'


  // 解密
 export const decrypt = (info)  => {

    var key = CryptoJS.enc.Utf8.parse(cryptoKey);
    let iv = CryptoJS.enc.Utf8.parse(ivStr);
    var decrypt = CryptoJS.AES.decrypt(info, key, {
        iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    return decrypt.toString(CryptoJS.enc.Utf8);
}

export const enCrypto = (info) => {
    const encryptedContent = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(info), CryptoJS.enc.Utf8.parse(cryptoKey), {
        iv: CryptoJS.enc.Utf8.parse(ivStr),
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });

    console.log(encryptedContent)
    const encStr = encryptedContent.toString()
    return encStr
}