feat: 后端完成双token刷新功能
This commit is contained in:
@@ -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<RbacOptions> options,
|
||||
IAliyunManger aliyunManger)
|
||||
IAliyunManger aliyunManger )
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_currentUser = currentUser;
|
||||
@@ -64,6 +62,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// <summary>
|
||||
/// 效验图片登录验证码,无需和账号绑定
|
||||
/// </summary>
|
||||
[AllowAnonymous]
|
||||
private void ValidationImageCaptcha(LoginInputVo input)
|
||||
{
|
||||
if (_rbacOptions.EnableCaptcha)
|
||||
@@ -83,6 +82,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
public async Task<object> 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 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新token
|
||||
/// </summary>
|
||||
/// <param name="refresh_token"></param>
|
||||
/// <returns></returns>
|
||||
[Authorize(AuthenticationSchemes = TokenTypeConst.Refresh)]
|
||||
public async Task<object> 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 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成验证码
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,5 +35,11 @@ namespace Yi.Framework.Rbac.Domain.Extensions
|
||||
return roleOrNull is null ? null : JsonConvert.DeserializeObject<List<RoleTokenInfoModel>>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
, IOptions<JwtOptions> jwtOptions
|
||||
, ILocalEventBus localEventBus
|
||||
, UserManager userManager
|
||||
,IOptions<RefreshJwtOptions> refreshJwtOptions
|
||||
, IOptions<RefreshJwtOptions> refreshJwtOptions
|
||||
, ISqlSugarRepository<RoleEntity> 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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<Claim> { new Claim("Refresh", "true") } ;
|
||||
//添加用户id,及刷新token的标识
|
||||
var claims = new List<Claim> {
|
||||
new Claim(AbpClaimTypes.UserId,userId.ToString()),
|
||||
new Claim(TokenTypeConst.Refresh, "true")
|
||||
};
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: _refreshJwtOptions.Issuer,
|
||||
audience: _refreshJwtOptions.Audience,
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
||||
{
|
||||
public interface IAccountManager : IDomainService
|
||||
{
|
||||
string CreateRefreshToken(Guid userId);
|
||||
Task<string> GetTokenByUserIdAsync(Guid userId);
|
||||
Task LoginValidationAsync(string userName, string password, Action<UserEntity> userAction = null);
|
||||
Task RegisterAsync(string userName, string password, long phone);
|
||||
|
||||
@@ -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<UserEntity>();
|
||||
|
||||
@@ -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 =>
|
||||
|
||||
Reference in New Issue
Block a user