知识点
- jwt身份认证
- md5加密
- typeorm事务(transaction)的使用
本文会延续上一篇文章,继续实现login功能,并实现API的身份认证,查看全部源码。
JWT身份认证
对与绝大多数应用程序来说,身份认证是必不可少的组成部分,而对用户的身份认证授权的策略和方法非常多,选用何种方法取决于项目的需求。
passport是node.js中的一个比较流行的认证库,本项目Demo会使用passport-jwt策略来实现用户身份认证。
JWT(Json Web Token)是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。
安装
npm install --save @nestjs/passport passport passport-jwt ?jsonwebtoken
添加jwt.stratagy.ts:
import { ExtractJwt, Strategy } from ‘passport-jwt‘;import { AuthService } from ‘./auth.service‘;import { PassportStrategy } from ‘@nestjs/passport‘;import { Injectable, UnauthorizedException } from ‘@nestjs/common‘;import { JwtPayload } from ‘./jwt-payload.interface‘@Injectable()export class JwtStrategy extends PassportStrategy(Strategy) { ?constructor(private readonly authService: AuthService) { ???super({ ?????jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ?????passReqToCallback: true, ?????secretOrKey: ‘secretKey‘, ???}); ?} ?async validate(payload: JwtPayload, done: Function) { ???console.log(‘entered jwt‘) ???const user = await this.authService.validateUser(payload.userNmae); ???if (!user) { ?????return done(new UnauthorizedException(), false); ???} ???done(null, user); ?}}
通过validate()方法获取token然后传递给auth.service进行验证。
添加autn.service.ts:
import { Injectable } from ‘@nestjs/common‘import { Repository } from ‘typeorm‘;import { JwtPayload } from ‘./jwt-payload.interface‘import * as jwt from ‘jsonwebtoken‘;import { Employee } from ‘../entities/employee.entity‘import { InjectRepository } from ‘@nestjs/typeorm‘;@Injectable()export class AuthService { ???user: Employee ???constructor( ???????@InjectRepository(Employee) ???????private readonly employeeRepository: Repository<Employee>) { } ???async createToken(userName: string, passwoerd: string): Promise<any> { ???????const user: JwtPayload = { userNmae: userName, passwoerd: passwoerd } ???????return jwt.sign(user, ‘secretKey‘, { expiresIn: 3600 }); ???} ???async validateUser(name: string): Promise<any> { ???????return this.employeeRepository.findOne({ name: name }); ???} ???async findEmployeeByName(name: string): Promise<Employee> { ???????return this.employeeRepository.findOne({ name: name }); ???} ???getUser(): Employee { ???????return this.user; ???} ???async login(name: string, password: string): Promise<any> { ???????this.user = await this.employeeRepository.findOne({ name: name }); ???????if (this.user != undefined && this.user.password == password) { ???????????return this.createToken(this.user.name, this.user.password); ???????} else { ???????????return ‘login failed !‘ ???????} ???}}
在auth.service中,createToken()用来生成Token信息,validateUser()验证身份信息,login用于用户登录,在login中先根据用户名查询用户验证密码,然后生成Token返回给前端。这里在生成token是指定了到期时间和secretkey.
auth.controller.ts:
import { Controller, Get, Param, UseGuards, HttpStatus, HttpCode } from ‘@nestjs/common‘;import { AuthService } from ‘./auth.service‘;import { AuthGuard } from ‘@nestjs/passport‘;import { callback } from ‘./jwt.strategy‘@Controller(‘auth‘)export class AuthController { ???constructor(private readonly authService: AuthService) { } ???@Get(‘login‘) ???@HttpCode(HttpStatus.OK) ???async login(@Param() params): Promise<any> { ???????return this.authService.login(params.name, params.password); ???} ???@Get(‘checklogin‘) ???@UseGuards(AuthGuard(‘jwt‘, { session: false, callback })) ???//@UseGuards(new RoleGuard([‘admin‘])) ???public checkLogin() { ???????return "valid user:" + this.authService.getUser().name; ???}
}
auth.controller中checklogin在访问时,使用passport的UserGuard配置jwt策略来验证身份信息,并在验证完成后指定调用callback函数。
MD5加密
本Demo使用了一个比较简单的加密策略,MD5。
安装包:
npm install --save @types/crypto-js crypto-js
加密过程也比较简单
import * as crypto from ‘crypto-js‘employee.password = crypto.MD5(‘123‘).toString();
typeorm 事务的使用(transaction)
事务在srvice中是比较常见的应用场景,在typeorm的官方文档中提供了多种方法来进行事务管理,本文介绍两种基本的使用方法。
1.getManager(隐式commit,隐式rollback)
async edit(): Promise<string> {if (employee) { ???????????return getManager().transaction(async transactionalEntityManager => { ???????????????await transactionalEntityManager.update<Employee>(Employee, { name: ‘novak‘ }, { age: 23 }); ???????????????await transactionalEntityManager.delete<Company>(Company, { id: 10 }); ???????????????let a = ‘123bew‘; ???????????????console.log(a[10].length);//制造异常 ???????????}).then(res => { ???????????????return ‘tranction done‘ ???????????}).catch(Error => { ???????????????return ‘tranction failed, ‘ + Error; ???????????}) ???????} else { ???????????return ‘employee not found‘; ???????} ???}
使用getManager().transaction来创建事务模块,为了验证效果,本文特意写了一个异常语句。验证结果是:出现异常后事务会自动回滚;如果没有异常,事务自动提交。
2.queryRunner(显式commit,显式rollback)
async editUseQueryRunner(): Promise<string> { ???????let employee = await this.employeeRepository.findOne({ name: "novak" }); ???????console.log(employee) ???????if (employee) { ???????????const connection = getConnection(); ???????????const queryRunner = connection.createQueryRunner(); ???????????await queryRunner.connect(); ???????????await queryRunner.startTransaction(); ???????????try { ???????????????await queryRunner.manager.update<Employee>(Employee, { name: ‘novak‘ }, { age: 24 }); ???????????????/* let a = ‘123bew‘; ???????????????console.log(a[10].length); */ ???????????????await queryRunner.commitTransaction(); ???????????????return ‘transaction done‘ ???????????} catch (err) { ???????????????await queryRunner.rollbackTransaction(); ???????????????return ‘transaction failed‘ ???????????} ???????} else { ???????????return ‘employee not found‘ ???????} ???}
从代码中就可以看到queryRunner是显式的提交和回滚事务的。
nest.js + typeORM:身份认证,事务管理
原文地址:https://www.cnblogs.com/novak12/p/9270950.html