diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs index a813b367..c7215b99 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/AccountService.cs @@ -1,7 +1,6 @@ using System.Text.RegularExpressions; using Lazy.Captcha.Core; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Options; @@ -10,7 +9,6 @@ using Volo.Abp; using Volo.Abp.Application.Services; using Volo.Abp.Authorization; using Volo.Abp.Caching; -using Volo.Abp.EventBus.Local; using Volo.Abp.Guids; using Volo.Abp.Uow; using Volo.Abp.Users; @@ -43,7 +41,7 @@ namespace Yi.Framework.Rbac.Application.Services ICaptcha captcha, IGuidGenerator guidGenerator, IOptions options, - IAliyunManger aliyunManger) + IAliyunManger aliyunManger ) { _userRepository = userRepository; _currentUser = currentUser; @@ -64,6 +62,7 @@ namespace Yi.Framework.Rbac.Application.Services /// /// 效验图片登录验证码,无需和账号绑定 /// + [AllowAnonymous] private void ValidationImageCaptcha(LoginInputVo input) { if (_rbacOptions.EnableCaptcha) @@ -83,6 +82,7 @@ namespace Yi.Framework.Rbac.Application.Services /// /// /// + [AllowAnonymous] public async Task PostLoginAsync(LoginInputVo input) { if (string.IsNullOrEmpty(input.Password) || string.IsNullOrEmpty(input.UserName)) @@ -99,11 +99,24 @@ namespace Yi.Framework.Rbac.Application.Services //获取token var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id); + var refreshToken = _accountManager.CreateRefreshToken(user.Id); - - return new { Token = accessToken }; + return new { Token = accessToken, RefreshToken = refreshToken }; } + /// + /// 刷新token + /// + /// + /// + [Authorize(AuthenticationSchemes = TokenTypeConst.Refresh)] + public async Task PostRefreshAsync([FromQuery] string refresh_token) + { + var userId = CurrentUser.Id.Value; + var accessToken = await _accountManager.GetTokenByUserIdAsync(userId); + var refreshToken = _accountManager.CreateRefreshToken(userId); + return new { Token = accessToken, RefreshToken = refreshToken }; + } /// /// 生成验证码 diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Consts/TokenTypeConst.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Consts/TokenTypeConst.cs index a0d66b3a..cab5fca9 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Consts/TokenTypeConst.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Consts/TokenTypeConst.cs @@ -25,5 +25,7 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts public const string Permission = nameof(Permission); public const string RoleInfo=nameof(RoleInfo); + + public const string Refresh=nameof(Refresh); } } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Extensions/CurrestUserExtensions.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Extensions/CurrestUserExtensions.cs index f94caa66..70380549 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Extensions/CurrestUserExtensions.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Extensions/CurrestUserExtensions.cs @@ -35,5 +35,11 @@ namespace Yi.Framework.Rbac.Domain.Extensions return roleOrNull is null ? null : JsonConvert.DeserializeObject>(roleOrNull); } + + public static bool IsRefreshToken(this ICurrentUser currentUser) + { + var refreshOrNull = currentUser.FindClaims(TokenTypeConst.Refresh).Select(x => x.Value).FirstOrDefault(); + return refreshOrNull is null ? false : bool.Parse(refreshOrNull); + } } } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs index 55c1b965..c4dadb9e 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/AccountManager.cs @@ -41,7 +41,7 @@ namespace Yi.Framework.Rbac.Domain.Managers , IOptions jwtOptions , ILocalEventBus localEventBus , UserManager userManager - ,IOptions refreshJwtOptions + , IOptions refreshJwtOptions , ISqlSugarRepository roleRepository) { _repository = repository; @@ -50,7 +50,7 @@ namespace Yi.Framework.Rbac.Domain.Managers _localEventBus = localEventBus; _userManager = userManager; _roleRepository = roleRepository; - _refreshJwtOptions= refreshJwtOptions.Value; + _refreshJwtOptions = refreshJwtOptions.Value; } /// @@ -112,11 +112,15 @@ namespace Yi.Framework.Rbac.Domain.Managers return returnToken; } - private string CreateRefreshToken() + public string CreateRefreshToken(Guid userId) { var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_refreshJwtOptions.SecurityKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); - var claims =new List { new Claim("Refresh", "true") } ; + //添加用户id,及刷新token的标识 + var claims = new List { + new Claim(AbpClaimTypes.UserId,userId.ToString()), + new Claim(TokenTypeConst.Refresh, "true") + }; var token = new JwtSecurityToken( issuer: _refreshJwtOptions.Issuer, audience: _refreshJwtOptions.Audience, diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs index b7c1b7cf..dd8b0e18 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain/Managers/IAccountManager.cs @@ -10,6 +10,7 @@ namespace Yi.Framework.Rbac.Domain.Managers { public interface IAccountManager : IDomainService { + string CreateRefreshToken(Guid userId); Task GetTokenByUserIdAsync(Guid userId); Task LoginValidationAsync(string userName, string password, Action userAction = null); Task RegisterAsync(string userName, string password, long phone); diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/YiRbacDbContext.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/YiRbacDbContext.cs index 26465c0b..2ffa92e1 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/YiRbacDbContext.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.SqlSugarCore/YiRbacDbContext.cs @@ -21,7 +21,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore { DataPermissionFilter(sqlSugarClient); } - + base.CustomDataFilter(sqlSugarClient); } @@ -33,7 +33,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore protected void DataPermissionFilter(ISqlSugarClient sqlSugarClient) { //获取当前用户的信息 - if (CurrentUser.Id == null) return; + if (CurrentUser.Id == null || CurrentUser.IsRefreshToken()) return; //管理员不过滤 if (CurrentUser.UserName.Equals(UserConst.Admin) || CurrentUser.Roles.Any(f => f.Equals(UserConst.AdminRolesCode))) return; var expUser = Expressionable.Create(); diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs index f1330f7f..33fdca00 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs +++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs @@ -25,6 +25,7 @@ using Yi.Framework.AspNetCore.Microsoft.AspNetCore.Builder; using Yi.Framework.AspNetCore.Microsoft.Extensions.DependencyInjection; using Yi.Framework.Bbs.Application; using Yi.Framework.Rbac.Application; +using Yi.Framework.Rbac.Domain.Shared.Consts; using Yi.Framework.Rbac.Domain.Shared.Options; namespace Yi.Abp.Web @@ -144,7 +145,7 @@ namespace Yi.Abp.Web } }; }) - .AddJwtBearer("Refresh", options => { + .AddJwtBearer(TokenTypeConst.Refresh, options => { options.TokenValidationParameters = new TokenValidationParameters { ClockSkew = TimeSpan.Zero, @@ -153,6 +154,18 @@ namespace Yi.Abp.Web ValidAudience = refreshJwtOptions.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey)) }; + options.Events = new JwtBearerEvents + { + OnMessageReceived = context => + { + var accessToken = context.Request.Query["refresh_token"]; + if (!string.IsNullOrEmpty(accessToken)) + { + context.Token = accessToken; + } + return Task.CompletedTask; + } + }; }) .AddQQ(options =>