monorepo-microservice-rbac/apps/services/dmp/gateway/src/guard/auth.guard.ts
2023-10-10 16:48:34 +08:00

76 lines
2.3 KiB
TypeScript

import {
Injectable,
CanActivate,
ExecutionContext,
ForbiddenException,
Inject,
} from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { firstValueFrom } from 'rxjs';
import { Request } from 'express';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(@Inject('Client') private readonly client: ClientProxy) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request: Request = context.switchToHttp().getRequest();
// 登录接口
if ('/dmp/auth/signIn' === request.url) {
const { username } = request.body;
const { allow } = await this.rolePermissionAllow(
{ username },
request.url,
);
if (!allow) throw new ForbiddenException('无权限访问');
return true;
}
// 获取token的配置
const { tokenKeyInCookie, tokenResignIn, expires } = await firstValueFrom(
this.client.send('cert.token.config', []),
);
const tokenCipher = request.cookies[tokenKeyInCookie];
if (!tokenCipher) throw new ForbiddenException('您没有执行此操作的权限');
// 1.验证token是否合法
const { tokenValid, payload } = await firstValueFrom(
this.client.send('cert.token.decode', tokenCipher),
);
if (!tokenValid) throw new ForbiddenException('您没有执行此操作的权限');
// 2.token续签
const { exp } = payload;
const tokenExpiredSoon = tokenResignIn * 1000 > exp * 1000 - Date.now();
if (tokenExpiredSoon) {
const { username } = payload;
const { token: newToken } = await firstValueFrom(
this.client.send('cert.token.create', { username }),
);
request.res.cookie(tokenKeyInCookie, newToken, {
maxAge: expires * 1000,
httpOnly: true,
});
}
// 3.验证角色授权
const { allow } = await this.rolePermissionAllow(payload, request.url);
if (!allow) throw new ForbiddenException('无权限访问');
return true;
}
/**
* 用户是否有权限
*/
async rolePermissionAllow(payload: { username: string }, requestUrl: string) {
const { allow } = await firstValueFrom(
this.client.send('cert.role.authorize', {
user: payload,
url: requestUrl,
}),
);
return { allow };
}
}