1. 程式人生 > >nest.js + typeORM:身份認證,事務管理

nest.js + typeORM:身份認證,事務管理

基本 his rac xtend 裝包 epo 多種方法 lse 用戶名

知識點

  • 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:身份認證,事務管理