1、项目的创建这些我们略过,如果还不会的同学,直接看文档。
2、jwt验证的实现,同样的 直接跟着文档来:https://docs.nestjs.com/security/authentication#jwt-functionality
3、user的entity这里改动下:
user/entities/user.entity.ts
import {
Entity,
Column,
PrimaryGeneratedColumn,
BeforeInsert,
ManyToMany,
JoinTable
} from 'typeorm';
import * as bcrypt from 'bcrypt';
import { Exclude, Transform } from 'class-transformer';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100, unique: true })
username: string;
@Column({ length: 100, unique: true })
email: string;
@Column({ nullable: true, length: 100 })
name: string;
@Column()
@Exclude({ toPlainOnly: true })
password: string;
@Column({ default: true })
is_active: boolean;
@Column({ default: false })
is_super: boolean;
@ManyToMany(() => Group)
@JoinTable()
groups: Group[];
@BeforeInsert()
async hashPassword() {
this.password = await bcrypt.hash(this.password, 10);
}
async set_password(password: string) {
this.password = await bcrypt.hash(password, 10);
}
async check_password(password: string): Promise<boolean> {
return await bcrypt.compare(password, this.password);
}
has_group(group:string){
let dt = false
this.groups.forEach(function(g){
if(g.name === group){
dt= true;
return false
}
})
return dt
}
has_permission(permission:string){
let dt = false
this.groups.forEach(function(group){
if(group.has_permission(permission)){
dt = true;
return false
}
})
return dt
}
}
@Entity()
export class Permission {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100, unique: true })
name: string;
@Column({ length: 100, default: '' })
desc: string;
}
@Entity()
export class Group {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 100, unique: true })
name: string;
@Column({ length: 100, default: '' })
desc: string;
@ManyToMany(() => Permission, { eager: true, })
@JoinTable()
permission: Permission[];
has_permission(permission:string){
let dt = false
this.permission.forEach(function(perm): boolean{
if(perm.name === permission){
dt = true
return false
}
})
return dt
}
}
这里涉及的是user跟group manytomany的关系,以及group跟permission的manytomany关系。
group包含has_permission方法,验证权限。
user包含has_group和has_permission方法,验证组以及权限。
4、在auth/jwt.strtegy.ts中修改:
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
+import { UserService } from '../user/services'
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private readonly userService: UserService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.JWT_SECRET,
});
}
async validate(payload: any) {
-const user = {username:payload.username, userId:payload.sub}
+const user = await this.userService.get(payload.sub)
return user;
}
}
官方的文档在jwt的validate只是简单的返回了jwt_token解密的userID和username.这里我们需要验证数据库并且返回User对象,这个User对象用于在request中,通过他的has_group方法以及has_permission方法来验证权限和组。
新增auth/role.permission.guard.ts,用于验证权限。
import {
Injectable,
CanActivate,
ExecutionContext,
UnauthorizedException,
SetMetadata
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
export const ermission_required = (permission: string) => SetMetadata('permission', permission);
@Injectable()
export class PermissionGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const permission = this.reflector.get<string>('permission', context.getHandler());
if (!permission) {
return false;
}
const request = context.switchToHttp().getRequest();
const user = request.user; // is undefined
// console.log(user,roles)
if (user && user.groups) {
// return roles.includes(user.groups);
return user.has_permission(permission)
} else {
throw new UnauthorizedException();
}
}
}
用法:
+import { PermissionGuard, Permission_required } from './auth/role/perms.guard'
@UseGuards(JwtAuthGuard, PermissionGuard)
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
@Get('profile')
@Permission_required('can_add_user') #权限needed
profile(@Request() request){
return request.user
}
}
本文由 admin 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Jan 15, 2021 at 06:02 pm