😎增加无效 Token 黑名单

This commit is contained in:
zuohuaijun 2025-02-04 16:33:49 +08:00
parent 11aea9c472
commit a0305e82d1
9 changed files with 46 additions and 26 deletions

View File

@ -82,9 +82,14 @@ public class CacheConst
public const string KeyOpenAccessNonce = "sys_open_access_nonce:";
/// <summary>
/// 登录黑名单
/// 用户黑名单
/// </summary>
public const string KeyBlacklist = "sys_blacklist:";
public const string KeyUserBlacklist = "sys_user_blacklist:";
/// <summary>
/// token黑名单
/// </summary>
public const string KeyTokenBlacklist = "sys_token_blacklist:";
/// <summary>
/// 系统配置缓存

View File

@ -100,7 +100,7 @@ public class OnlineUserHub : Hub<IOnlineUserHub>
{
if (string.IsNullOrEmpty(Context.ConnectionId)) return;
var httpContext = Context.GetHttpContext();
//var httpContext = Context.GetHttpContext();
var user = await _sysOnlineUerRep.AsQueryable().Filter("", true).FirstAsync(u => u.ConnectionId == Context.ConnectionId);
if (user == null) return;

View File

@ -313,17 +313,17 @@ public class SysAuthService : IDynamicApiController, ITransient
};
}
/// <summary>
/// 获取刷新Token 🔖
/// </summary>
/// <param name="accessToken"></param>
/// <returns></returns>
[DisplayName("获取刷新Token")]
public string GetRefreshToken([FromQuery] string accessToken)
{
var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult();
return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
}
///// <summary>
///// 获取刷新Token 🔖
///// </summary>
///// <param name="accessToken"></param>
///// <returns></returns>
//[DisplayName("获取刷新Token")]
//public string GetRefreshToken([FromQuery] string accessToken)
//{
// var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult();
// return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
//}
/// <summary>
/// 退出系统 🔖
@ -334,9 +334,15 @@ public class SysAuthService : IDynamicApiController, ITransient
if (string.IsNullOrWhiteSpace(_userManager.Account))
throw Oops.Oh(ErrorCodeEnum.D1011);
// 增加无效Token黑名单
var tokenExpire = await _sysConfigService.GetTokenExpire();
var accessToken = _httpContextAccessor.HttpContext.Request.Headers.Authorization.ToString();
_sysCacheService.Set($"{CacheConst.KeyTokenBlacklist}{accessToken}", $"{_userManager.UserId}-{_userManager.Account}-{_userManager.RealName}-{DateTime.Now}", TimeSpan.FromMinutes(tokenExpire));
// 发布系统退出事件
await _eventPublisher.PublishAsync(UserEventTypeEnum.Logout, _userManager);
// 退出Swagger/设置无效Token响应头
_httpContextAccessor.HttpContext.SignoutToSwagger();
}

View File

@ -222,7 +222,7 @@ public class SysConfigService : IDynamicApiController, ITransient
}
/// <summary>
/// 获取 Token 过期时间
/// 获取 Token 过期时间/分钟
/// </summary>
/// <returns></returns>
[NonAction]
@ -234,7 +234,7 @@ public class SysConfigService : IDynamicApiController, ITransient
}
/// <summary>
/// 获取 RefreshToken 过期时间
/// 获取 RefreshToken 过期时间/分钟
/// </summary>
/// <returns></returns>
[NonAction]

View File

@ -276,16 +276,16 @@ public class SysUserService : IDynamicApiController, ITransient
[NonAction]
private async Task SetUserBalckList(SysUser user, StatusEnum status)
{
// 账号禁用则增加黑名单,账号启用则移除黑名单
// 禁用账号则增加黑名单,启用账号则移除黑名单
var sysCacheService = App.GetRequiredService<SysCacheService>();
if (status != StatusEnum.Enable)
{
sysCacheService.Set($"{CacheConst.KeyBlacklist}{user.Id}", $"{user.RealName}-{user.Phone}");
sysCacheService.Set($"{CacheConst.KeyUserBlacklist}{user.Id}", $"{user.RealName}-{user.Phone}");
await _sysOnlineUserService.ForceOffline(user.Id); // 强制账号下线
}
else
{
sysCacheService.Remove($"{CacheConst.KeyBlacklist}{user.Id}");
sysCacheService.Remove($"{CacheConst.KeyUserBlacklist}{user.Id}");
}
}

View File

@ -7,7 +7,7 @@
namespace Admin.NET.Core;
/// <summary>
/// 当前登录用户
/// 当前登录用户信息
/// </summary>
public class UserManager : IScoped
{

View File

@ -39,11 +39,20 @@ namespace Admin.NET.Web.Core
// var serviceProvider = context.GetCurrentHttpContext().RequestServices;
using var serviceScope = _serviceProvider.CreateScope();
// 若当前账号存在黑名单中则授权失败
// 验证账号黑名单有则授权失败
var sysCacheService = serviceScope.ServiceProvider.GetRequiredService<SysCacheService>();
if (sysCacheService.ExistKey($"{CacheConst.KeyBlacklist}{context.User.FindFirst(ClaimConst.UserId)?.Value}"))
if (sysCacheService.ExistKey($"{CacheConst.KeyUserBlacklist}{context.User.FindFirst(ClaimConst.UserId)?.Value}"))
{
context.Fail();
context.Fail(new AuthorizationFailureReason(this, "账号已经黑名单,请联系相关管理人员。"));
context.GetCurrentHttpContext().SignoutToSwagger();
return;
}
// 验证Token黑名单有则授权失败
var accessToken = httpContext.Request.Headers.Authorization.ToString();
if (sysCacheService.ExistKey($"{CacheConst.KeyTokenBlacklist}{accessToken}"))
{
context.Fail(new AuthorizationFailureReason(this, "Token已失效请重新登录。"));
context.GetCurrentHttpContext().SignoutToSwagger();
return;
}

View File

@ -30,7 +30,7 @@ public class SuperApiAop : DefaultSuperApiAop
throw Oops.Oh("没权限 Unauthorized");
//}
var accessToken = aopContext.HttpContext.Request.Headers["Authorization"].ToString();
var accessToken = aopContext.HttpContext.Request.Headers.Authorization.ToString();
var (isValid, tokenData, validationResult) = JWTEncryption.Validate(accessToken.Replace("Bearer ", ""));
if (!isValid)
throw Oops.Oh("Token 无效");
@ -62,7 +62,7 @@ public class SuperApiAop : DefaultSuperApiAop
var api = aopContext.InterfaceInfo;
var context = aopContext.HttpContext;
var accessToken = context.Request.Headers["Authorization"].ToString();
var accessToken = context.Request.Headers.Authorization.ToString();
if (!string.IsNullOrWhiteSpace(accessToken) && accessToken.StartsWith("Bearer "))
accessToken = accessToken.Replace("Bearer ", "");
var claims = JWTEncryption.ReadJwtToken(accessToken)?.Claims;

View File

@ -74,7 +74,7 @@
"vue-router": "^4.5.0",
"vue-signature-pad": "^3.0.2",
"vue3-tree-org": "^4.2.2",
"vxe-pc-ui": "^4.3.78",
"vxe-pc-ui": "^4.3.79",
"vxe-table": "^4.10.0",
"vxe-table-plugin-element": "^4.0.4",
"vxe-table-plugin-export-xlsx": "^4.0.7",