76 lines
2.3 KiB
TypeScript
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 };
|
|
}
|
|
}
|