From 03de3abe08597fa93c740800b92c21fb264ffd0c Mon Sep 17 00:00:00 2001 From: LemonNoCry <773596523@qq.com> Date: Sat, 23 Jul 2022 18:51:35 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Token=20=E5=A2=9E=E5=8A=A0=E7=AD=BE?= =?UTF-8?q?=E5=90=8D=E6=97=B6=E9=97=B4=20=F0=9F=90=9B=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E5=B0=8Fbug=20MessageModel.success=20?= =?UTF-8?q?=E8=B5=8B=E5=80=BC=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.解决用户修改关键信息后(如修改密码、修改名称等等) token不会失效 2.可解决用户修改部门、角色、权限后 token失效 只需要刷新User的修改时间 --- Blog.Core.Api/Controllers/LoginController.cs | 2 + .../HttpContextUser/AspNetUser.cs | 3 ++ Blog.Core.Common/HttpContextUser/IUser.cs | 3 ++ .../Policys/ApiResponseHandler.cs | 22 +++++++--- .../Policys/PermissionHandler.cs | 42 +++++++++++++++---- Blog.Core.Model/ApiResponse.cs | 40 +++++++++--------- 6 files changed, 77 insertions(+), 35 deletions(-) diff --git a/Blog.Core.Api/Controllers/LoginController.cs b/Blog.Core.Api/Controllers/LoginController.cs index 63ab143..089c286 100644 --- a/Blog.Core.Api/Controllers/LoginController.cs +++ b/Blog.Core.Api/Controllers/LoginController.cs @@ -160,6 +160,7 @@ namespace Blog.Core.Controllers var claims = new List { new Claim(ClaimTypes.Name, name), new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault().Id.ToString()), + new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()), new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) }; claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s))); @@ -214,6 +215,7 @@ namespace Blog.Core.Controllers var claims = new List { new Claim(ClaimTypes.Name, user.LoginName), new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()), + new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()), new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) }; claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s))); diff --git a/Blog.Core.Common/HttpContextUser/AspNetUser.cs b/Blog.Core.Common/HttpContextUser/AspNetUser.cs index a2aa672..e4e27d8 100644 --- a/Blog.Core.Common/HttpContextUser/AspNetUser.cs +++ b/Blog.Core.Common/HttpContextUser/AspNetUser.cs @@ -2,6 +2,7 @@ using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; +using Blog.Core.Model; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; @@ -70,6 +71,8 @@ namespace Blog.Core.Common.HttpContextUser return new List() { }; } + public MessageModel MessageModel { get; set; } + public IEnumerable GetClaimsIdentity() { var claims = _accessor.HttpContext.User.Claims.ToList(); diff --git a/Blog.Core.Common/HttpContextUser/IUser.cs b/Blog.Core.Common/HttpContextUser/IUser.cs index 3ab11bd..beef3b7 100644 --- a/Blog.Core.Common/HttpContextUser/IUser.cs +++ b/Blog.Core.Common/HttpContextUser/IUser.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Security.Claims; +using Blog.Core.Model; namespace Blog.Core.Common.HttpContextUser { @@ -13,5 +14,7 @@ namespace Blog.Core.Common.HttpContextUser string GetToken(); List GetUserInfoFromToken(string ClaimType); + + MessageModel MessageModel { get; set; } } } diff --git a/Blog.Core.Extensions/Authorizations/Policys/ApiResponseHandler.cs b/Blog.Core.Extensions/Authorizations/Policys/ApiResponseHandler.cs index 6aedc54..9c8f4e5 100644 --- a/Blog.Core.Extensions/Authorizations/Policys/ApiResponseHandler.cs +++ b/Blog.Core.Extensions/Authorizations/Policys/ApiResponseHandler.cs @@ -7,19 +7,24 @@ using Newtonsoft.Json; using System; using System.Text.Encodings.Web; using System.Threading.Tasks; +using Blog.Core.Common.HttpContextUser; namespace Blog.Core.AuthHelper { public class ApiResponseHandler : AuthenticationHandler { - public ApiResponseHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) + private readonly IUser _user; + + public ApiResponseHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IUser user) : base(options, logger, encoder, clock) { + _user = user; } protected override Task HandleAuthenticateAsync() { throw new NotImplementedException(); } + protected override async Task HandleChallengeAsync(AuthenticationProperties properties) { Response.ContentType = "application/json"; @@ -30,9 +35,16 @@ namespace Blog.Core.AuthHelper protected override async Task HandleForbiddenAsync(AuthenticationProperties properties) { Response.ContentType = "application/json"; - Response.StatusCode = StatusCodes.Status403Forbidden; - await Response.WriteAsync(JsonConvert.SerializeObject((new ApiResponse(StatusCode.CODE403)).MessageModel)); + if (_user.MessageModel != null) + { + Response.StatusCode = _user.MessageModel.status; + await Response.WriteAsync(JsonConvert.SerializeObject(_user.MessageModel)); + } + else + { + Response.StatusCode = StatusCodes.Status403Forbidden; + await Response.WriteAsync(JsonConvert.SerializeObject((new ApiResponse(StatusCode.CODE403)).MessageModel)); + } } - } -} +} \ No newline at end of file diff --git a/Blog.Core.Extensions/Authorizations/Policys/PermissionHandler.cs b/Blog.Core.Extensions/Authorizations/Policys/PermissionHandler.cs index 8bb41e4..91ac59c 100644 --- a/Blog.Core.Extensions/Authorizations/Policys/PermissionHandler.cs +++ b/Blog.Core.Extensions/Authorizations/Policys/PermissionHandler.cs @@ -7,10 +7,13 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Blog.Core.Common.HttpContextUser; +using Blog.Core.Model; namespace Blog.Core.AuthHelper { @@ -23,8 +26,11 @@ namespace Blog.Core.AuthHelper /// 验证方案提供对象 /// public IAuthenticationSchemeProvider Schemes { get; set; } + private readonly IRoleModulePermissionServices _roleModulePermissionServices; private readonly IHttpContextAccessor _accessor; + private readonly ISysUserInfoServices _userServices; + private readonly IUser _user; /// /// 构造函数注入 @@ -32,9 +38,13 @@ namespace Blog.Core.AuthHelper /// /// /// - public PermissionHandler(IAuthenticationSchemeProvider schemes, IRoleModulePermissionServices roleModulePermissionServices, IHttpContextAccessor accessor) + /// + /// + public PermissionHandler(IAuthenticationSchemeProvider schemes, IRoleModulePermissionServices roleModulePermissionServices, IHttpContextAccessor accessor, ISysUserInfoServices userServices, IUser user) { _accessor = accessor; + _userServices = userServices; + _user = user; Schemes = schemes; _roleModulePermissionServices = roleModulePermissionServices; } @@ -74,6 +84,7 @@ namespace Blog.Core.AuthHelper Role = item.Role?.Name.ObjToString(), }).ToList(); } + requirement.Permissions = list; } @@ -114,7 +125,6 @@ namespace Blog.Core.AuthHelper //result?.Principal不为空即登录成功 if (result?.Principal != null || isTestCurrent) { - if (!isTestCurrent) httpContext.User = result.Principal; // 获取当前用户的角色信息 @@ -160,6 +170,7 @@ namespace Blog.Core.AuthHelper return; } + // 判断token是否过期,过期则重新登录 var isExp = false; // ids4和jwt切换 // ids4 @@ -172,18 +183,31 @@ namespace Blog.Core.AuthHelper // jwt isExp = (httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now; } - if (isExp) + + if (!isExp) { - context.Succeed(requirement); - } - else - { - context.Fail(); + context.Fail(new AuthorizationFailureReason(this, "授权已过期,请重新授权")); return; } + + //校验签发时间 + var value = httpContext.User.Claims.SingleOrDefault(s => s.Type == JwtRegisteredClaimNames.Iat)?.Value; + if (value != null) + { + var user = await _userServices.QueryById(_user.ID, true); + if (user.UpdateTime > value.ObjToDate()) + { + _user.MessageModel = new ApiResponse(StatusCode.CODE403, "很抱歉,授权已失效,请重新授权").MessageModel; + context.Fail(new AuthorizationFailureReason(this, _user.MessageModel.msg)); + return; + } + } + + context.Succeed(requirement); return; } } + //判断没有登录时,是否访问登录的url,并且是Post请求,并且是form表单提交类型,否则为失败 if (!(questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasFormContentType))) { @@ -195,4 +219,4 @@ namespace Blog.Core.AuthHelper //context.Succeed(requirement); } } -} +} \ No newline at end of file diff --git a/Blog.Core.Model/ApiResponse.cs b/Blog.Core.Model/ApiResponse.cs index 0927aca..74944ae 100644 --- a/Blog.Core.Model/ApiResponse.cs +++ b/Blog.Core.Model/ApiResponse.cs @@ -1,5 +1,4 @@ - -namespace Blog.Core.Model +namespace Blog.Core.Model { public class ApiResponse { @@ -12,28 +11,28 @@ namespace Blog.Core.Model switch (apiCode) { case StatusCode.CODE401: - { - Status = 401; - Value = "很抱歉,您无权访问该接口,请确保已经登录!"; - } + { + Status = 401; + Value = msg ?? "很抱歉,您无权访问该接口,请确保已经登录!"; + } break; case StatusCode.CODE403: - { - Status = 403; - Value = "很抱歉,您的访问权限等级不够,联系管理员!"; - } + { + Status = 403; + Value = msg ?? "很抱歉,您的访问权限等级不够,联系管理员!"; + } break; case StatusCode.CODE404: - { - Status = 404; - Value = "资源不存在!"; - } + { + Status = 404; + Value = "资源不存在!"; + } break; case StatusCode.CODE500: - { - Status = 500; - Value = msg; - } + { + Status = 500; + Value = msg; + } break; } @@ -41,7 +40,7 @@ namespace Blog.Core.Model { status = Status, msg = Value, - success = apiCode != StatusCode.CODE200 + success = apiCode == StatusCode.CODE200 }; } } @@ -54,5 +53,4 @@ namespace Blog.Core.Model CODE404, CODE500 } - -} +} \ No newline at end of file