parent
5e4a81c303
commit
ad853c326e
@ -1,10 +1,9 @@ |
||||
import { Module } from '@nestjs/common'; |
||||
import { AuthUserService } from './auth-user.service'; |
||||
import { AuthUserController } from './auth-user.controller'; |
||||
import { JwtService } from '@common/service/jwt/jwt.service'; |
||||
|
||||
@Module({ |
||||
controllers: [AuthUserController], |
||||
providers: [AuthUserService, JwtService], |
||||
providers: [AuthUserService], |
||||
}) |
||||
export class AuthUserModule {} |
||||
|
@ -1,15 +1,14 @@ |
||||
import { createParamDecorator, ExecutionContext, SetMetadata } from '@nestjs/common'; |
||||
import { PacInfoType } from '@utils/myType'; |
||||
import { GuardInfo } from '@utils/myType'; |
||||
|
||||
// export const PacInfo = (...args: string[]) => SetMetadata('pac-info', args);
|
||||
// export const UserInfoDecorator = (...args: string[]) => SetMetadata('pac-info', args);
|
||||
|
||||
// PacInfo
|
||||
export const PacInfo = createParamDecorator((data: string, ctx: ExecutionContext) => { |
||||
const info: PacInfoType = { |
||||
username: 'pac', |
||||
userId: 0, |
||||
// UserInfoDecorator
|
||||
export const UserInfoDecorator = createParamDecorator((data: string, ctx: ExecutionContext) => { |
||||
const request = ctx.switchToHttp().getRequest(); |
||||
const info: GuardInfo = { |
||||
username: request.guardInfo.username, |
||||
userId: request.guardInfo.userId, |
||||
}; |
||||
return info; |
||||
|
||||
// const req = ctx.switchToHttp().getRequest();
|
||||
}); |
||||
|
@ -0,0 +1,82 @@ |
||||
import { CanActivate, ExecutionContext, HttpException, HttpStatus, Injectable } from '@nestjs/common'; |
||||
import { Observable } from 'rxjs'; |
||||
import { LoggerService } from '@service/logger/logger.service'; |
||||
import { MysqlService } from '@common/service/mysql/mysql.service'; |
||||
import { RedisService } from '@common/service/redis/redis.service'; |
||||
import { Snowflake } from '@service/snowflake/snowflake.service'; |
||||
import { ConfigService } from '@nestjs/config'; |
||||
import { JwtService } from '@common/service/jwt/jwt.service'; |
||||
import { KEY } from '@utils/key'; |
||||
import MD5 from '@utils/MD5'; |
||||
|
||||
@Injectable() |
||||
export class AuthGuard implements CanActivate { |
||||
constructor( |
||||
private readonly logger: LoggerService, |
||||
private readonly mysqlService: MysqlService, |
||||
private readonly redisService: RedisService, |
||||
private readonly snowflake: Snowflake, |
||||
private readonly config: ConfigService, |
||||
private readonly jwt: JwtService, |
||||
) {} |
||||
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> { |
||||
const request = context.switchToHttp().getRequest(); |
||||
|
||||
// ! 路由白名单
|
||||
const whitelist = this.config.get<string[]>('system.whitelist'); |
||||
if (whitelist.some((route) => request.url.startsWith(route))) { |
||||
// ! 如果请求的路径在白名单中,允许直接访问
|
||||
return true; |
||||
} |
||||
return new Promise(async (resolve, reject) => { |
||||
if (request.headers.authorization) { |
||||
let authorization = request.headers.authorization; |
||||
if (authorization.indexOf('Bearer ') === 0) { |
||||
authorization = authorization.split('Bearer ')[1]; |
||||
} |
||||
|
||||
// ! 获取Token
|
||||
let token; |
||||
try { |
||||
token = (await this.jwt.verify(authorization)) as any; |
||||
} catch (e) { |
||||
token = undefined; |
||||
this.logger.warn('令牌解析错误', e, e.track); |
||||
} |
||||
|
||||
// ? 判断Token是否过期
|
||||
if (token === undefined) { |
||||
return reject(new HttpException('FORBIDDEN | 令牌过期!', HttpStatus.FORBIDDEN)); |
||||
} |
||||
|
||||
// ? 判断redis中是否存在
|
||||
const redisTokenKey = |
||||
token.type == 'refreshToken' |
||||
? KEY.REDIS_REFRESH_TOKEN + token.userId + '-' + MD5(authorization) |
||||
: KEY.REDIS_TOKEN + token.userId + '-' + MD5(authorization); |
||||
const redisToken = await this.redisService.get(redisTokenKey); |
||||
if (redisToken == null) { |
||||
console.log('??????'); |
||||
return reject(new HttpException('FORBIDDEN | 令牌过期!', HttpStatus.FORBIDDEN)); |
||||
} |
||||
|
||||
// ? 是否是refreshToken访问非token刷新接口
|
||||
if (token.type == 'refreshToken' && request.url !== '/authUser/sign/refresh') { |
||||
return reject(new HttpException('BAD_REQUEST | 令牌使用错误!', HttpStatus.BAD_REQUEST)); |
||||
} |
||||
|
||||
// ? 是否是token访问token刷新接口
|
||||
|
||||
if (token.type == 'token' && request.url == '/authUser/sign/refresh') { |
||||
return reject(new HttpException('BAD_REQUEST | 令牌使用错误,非法续约!', HttpStatus.BAD_REQUEST)); |
||||
} |
||||
|
||||
// 假设token有效
|
||||
resolve(true); |
||||
request.guardInfo = token; |
||||
} else { |
||||
reject(new HttpException('Unauthorized | 你没有访问权限!', HttpStatus.UNAUTHORIZED)); |
||||
} |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,32 @@ |
||||
// | ------------------------------------------------------------
|
||||
// | @版本: version 0.1
|
||||
// | @创建人: 【Nie-hotok】
|
||||
// | @E-mail: x71291@outlook.com
|
||||
// | @所在项目: pac-auth
|
||||
// | @文件描述: key.ts -
|
||||
// | @创建时间: 2024-06-30 10:44
|
||||
// | @更新时间: 2024-06-30 10:44
|
||||
// | @修改记录:
|
||||
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||
// | =
|
||||
// | ------------------------------------------------------------
|
||||
export const KEY = { |
||||
// ! 正常请求Token的Redis前缀
|
||||
REDIS_TOKEN: 'CLIENT-ONLINE-', |
||||
|
||||
// ! 刷新Token的Redis前缀
|
||||
REDIS_REFRESH_TOKEN: 'CLIENT-', |
||||
|
||||
// ! 最大客户端登陆数量的Redis前缀
|
||||
REDIS_MAX_CLIENT: 'ENV_MAX_SIGNIN_CLIENT', |
||||
|
||||
// ! 客户端登陆错误的次数 Redis前缀
|
||||
REDIS_FIELD_SIGNIN_NUM: 'FIELD_SIGNIN_NUM-', |
||||
|
||||
// ! 系统允许的最大错误登录数量
|
||||
REDIS_MAX_FIELD_SIGNIN_NUM: 'MAX_FIELD_SIGNIN_NUM', |
||||
|
||||
// ! 最大登录失败后的冷却时间
|
||||
REDIS_WAITING_SIGNIN_TIME: 'CONFIG_MAX_TIME_FIELD_SIGNIN', |
||||
|
||||
}; |
Loading…
Reference in new issue