nest authGuard 守卫做登录鉴权练习

修改用户的实体类 userEntity
  • 处理密码加密方式
import {
	Entity,
	PrimaryGeneratedColumn,
	Column,
	CreateDateColumn,
	UpdateDateColumn,
	BeforeInsert
} from "typeorm"
import NodeAuth from "node-auth0"
import { Exclude, Expose } from "class-transformer" 
import * as jwt from "jsonwebtoken"

@Entity({name: "user"})
export class UserEntity {
	@Exclude()
	private nodeAuth: NodeAuth

	constructor () {
		this.nodeAuth = new NodeAuth()
	}	

	@Expose()
	private get token() {
		const { username, id } = this
		return jwt.sign(
			{ id, username },
			process.env.SECRET,
			{ expiresIn: "7d" }
		)
	}

	public toResponseObject(isShowToken = true): {[key: string]: any} {
		const { nodeAuth, password, token, username, ...params } = this
		const responseData = {
			username,
			...params
		}

		if (isShowToken) {
			return Object.assign(responseData, { token })
		} else {
			return responseData
		}
	}

	@PrimaryGeneratedColumn({
		type: "int",
		name: "id",
		comment: "主键id"
	})
	id: number

	@Column({
		type: "varchar",
		nullable: true,
		length: 50,
		unique: true,
		name: "username",
		comment: "用户名"
	})
	username: string

	@Column({
		type: "varchar",
		nullable: false,
		length: 20,
		default: "123456",
		name: "password",
		comment: "密码"
	})
	password: string

  @Column({
    type: 'varchar',
    nullable: true,
    length: 50,
    name: 'email',
    comment: "邮箱"
  })
  email: string;

  @Column({
    type: 'varchar',
    nullable: true,
    length: 11,
    name: 'mobile',
    comment: "手机号"
  })
  mobile: string;

  @Column('tinyint', {
    nullable: true,
    default: () => 0,
    name: 'is_del',
    comment: '是否删除,1表示删除,0表示正常'
  })
  isDel: number;

  @CreateDateColumn({
    type: 'timestamp',
    nullable: true,
    name: 'created_at',
    comment: '创建时间'
  })
  createdAt: Date;

  @UpdateDateColumn({
    type: 'timestamp',
    nullable: true,
    name: 'updated_at',
    comment: '更新时间',
  })
  updateAt: Date;

  @BeforeInsert()
  makePassword(): void {
    this.password = this.nodeAuth.makePassword(this.password);
  }
}
  • 登录的时候校验用户名和密码及返回token
    LoginService
import { Injectable } from "@nestjs/common"
import { Respository, getManager, EntityManager } from "typeorm"
import { UserEntity } from "../user.entity"
import NodeAuth from "node-auth0"
import { jwt } from "../../../utils/jwt"
import { RedisUtilsService } from "../../redis-utils/redis-utils.service"

type CommonType = {[key: string]: any}

@Injectable()
export class LoginService {
	private nodeAuth: NodeAuth

	constructor (
		private redisUtilsService: RedisUtilsService
	) {
		this.nodeAuth = new NodeAuth()
	}

	async login(data: CommonType): Promise<any | string> {
		const { username, password } = data
		return getManager()
			.transaction(async (manager: EntityManager) => {
				const user = await manager.findOne(UserEntity, { username })
				if (
					user && 
					this.nodeAuth.checkPassword(password, user,password)
				) {
					const token = jwt.createToken(String(user.id))
					const redisData = {
						token,
						user
					}
					this.redisUtilsService.set(String(user.id), redisData)
					return { ...user, token }
				} else { 
					return "账号或密码错误"
				}
			})
			.then(res => {

			})
			.catch(err => {
				console.log(err)
			})
	}
}
  • authGuard
import {
	Injectable,
	canActivate,
	Logger,
	HttpException,
	HttpStatus,
	ExecutionContext
} from "@nestjs/common"
import { Observable } from "rxjs"
import { jwt } from "../utils/jwt"
import * as url from "url"
import { RedisUtilsService } from "../modules/redis-utils/redis-utils.service"

@Injectable()
export class AuthGuard implements canActivate {
	constructor(
		private redisUtilsService: RedisUtilsService
	) {}

	async canActivate(
		context: ExecutionContext		
	): Promise<boolean> {
		const request = context.switchToHttp().getRequest()
		const token = 
			context.switchToRpc().getData().headers.token ||
			context.switchToHttp().getData().body.token ||
			this.getUrlQuery(request.url, "token")
		
		Logger.log(`当前的token: ${token}`, "AuthGuard")
		
		if (token) {
			const currentUserId = jwt.decodeToken(token)
			const redisData = await this.redisUtilsService.get(currentUserId)
			console.log(JSON.stringify(redisData, "redis数据"))
			if (Object.is(token, redisData.token)) {
				request.user = redisData.token
				return true
			} else {
				throw new HttpException("token已经失效,请重新登录", HttpStatus.UNAUTHORIZED)
			}
		} else {
			throw new HttpException("你还没有登录,请先登录", HttpStatus.UNAUTHORIZED)
		}
	}

	private getUrlQuery(urlPath: string, key?: string): string | {[key: string]: any} {
		const query = url.parse(urlPath, true).query
		if (key) {
			return query[key]
		} else {
			return query
		}
	}
}
  • 使用redis做单点登录
    redisUtilsModue 在app中引入 全局使用
import { Module, Global } from '@nestjs/common';
import { RedisModule } from 'nestjs-redis'
import { RedisUtilsService } from './redis-utils.service';

@Global()
@Module({
  imports: [
    RedisModule.register({ // 配置redis的基本信息
      port: 6379,
      host: '127.0.0.1',
      password: '',
      db: 0
    })
  ],
  providers: [
    RedisUtilsService,
  ],
  exports: [
    RedisUtilsService,
  ]
})
export class RedisUtilsModule { }
  • redis-utils.service.ts
import { Injectable } from "@nestjs/common"
import { RedisService } from "nestjs-redis"
import { Redis } from "ioredis"

@Injectable()
export class RedisUtilsService {
	public client: Redis
	constructor (
		private redisService: RedisService
	) {}
	
	onModuleInit(): void {
		this.getClient()
	}

	public getClient(): void {
		this.client = this.redisService.getClient()
	}

	public async set(key: string, value: {[key: string]: any} | string , second?: number): Promise<void> {
		value = JSON.stringify(value)
		if (!second) {
			await this.client.setex(key, 24 * 60 * 60, value)
		} else {
			await this.client.set(key, value, "EX", second)
		}
	}

	public async get(key: string): Promise<any> {
		const data = await this.client.get(key)
		if (data) {
			return JSON.parse(data)
		} else {
			return null
		}
	}

	public async del(key: string): Promise<any> {
		await this.client.del(key)
	}

	public async flushall(): Promise<any> {
		await this.client.flushall()
	}
}
  • utils下创建jwt.js
import NodeSSO from "node-sso"

class JWT {
	private nodeSSO: NodeSSO
	constructor (secret: string) {
		this.nodeSSO = new NodeSSO(secret)
	}
	
	public createToken(user: string | {[key: string]: any}): string {
		return this.nodeSSO.generateToken(user)
	}

	public decodeToken(token: string): string | null {
		return this.nodeSSO.decryptToken(token)
	}
}

export const jwt = new JWT(process.env.SECRET)
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值