feat: 后端完成双token刷新功能
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Lazy.Captcha.Core;
|
using Lazy.Captcha.Core;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
@@ -10,7 +9,6 @@ using Volo.Abp;
|
|||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
using Volo.Abp.Authorization;
|
using Volo.Abp.Authorization;
|
||||||
using Volo.Abp.Caching;
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.EventBus.Local;
|
|
||||||
using Volo.Abp.Guids;
|
using Volo.Abp.Guids;
|
||||||
using Volo.Abp.Uow;
|
using Volo.Abp.Uow;
|
||||||
using Volo.Abp.Users;
|
using Volo.Abp.Users;
|
||||||
@@ -43,7 +41,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
ICaptcha captcha,
|
ICaptcha captcha,
|
||||||
IGuidGenerator guidGenerator,
|
IGuidGenerator guidGenerator,
|
||||||
IOptions<RbacOptions> options,
|
IOptions<RbacOptions> options,
|
||||||
IAliyunManger aliyunManger)
|
IAliyunManger aliyunManger )
|
||||||
{
|
{
|
||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
_currentUser = currentUser;
|
_currentUser = currentUser;
|
||||||
@@ -64,6 +62,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 效验图片登录验证码,无需和账号绑定
|
/// 效验图片登录验证码,无需和账号绑定
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[AllowAnonymous]
|
||||||
private void ValidationImageCaptcha(LoginInputVo input)
|
private void ValidationImageCaptcha(LoginInputVo input)
|
||||||
{
|
{
|
||||||
if (_rbacOptions.EnableCaptcha)
|
if (_rbacOptions.EnableCaptcha)
|
||||||
@@ -83,6 +82,7 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[AllowAnonymous]
|
||||||
public async Task<object> PostLoginAsync(LoginInputVo input)
|
public async Task<object> PostLoginAsync(LoginInputVo input)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(input.Password) || string.IsNullOrEmpty(input.UserName))
|
if (string.IsNullOrEmpty(input.Password) || string.IsNullOrEmpty(input.UserName))
|
||||||
@@ -99,11 +99,24 @@ namespace Yi.Framework.Rbac.Application.Services
|
|||||||
|
|
||||||
//获取token
|
//获取token
|
||||||
var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id);
|
var accessToken = await _accountManager.GetTokenByUserIdAsync(user.Id);
|
||||||
|
var refreshToken = _accountManager.CreateRefreshToken(user.Id);
|
||||||
|
|
||||||
|
return new { Token = accessToken, RefreshToken = refreshToken };
|
||||||
return new { Token = accessToken };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
/// <summary>
|
||||||
/// 生成验证码
|
/// 生成验证码
|
||||||
|
|||||||
@@ -25,5 +25,7 @@ namespace Yi.Framework.Rbac.Domain.Shared.Consts
|
|||||||
public const string Permission = nameof(Permission);
|
public const string Permission = nameof(Permission);
|
||||||
|
|
||||||
public const string RoleInfo=nameof(RoleInfo);
|
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);
|
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
|
, IOptions<JwtOptions> jwtOptions
|
||||||
, ILocalEventBus localEventBus
|
, ILocalEventBus localEventBus
|
||||||
, UserManager userManager
|
, UserManager userManager
|
||||||
,IOptions<RefreshJwtOptions> refreshJwtOptions
|
, IOptions<RefreshJwtOptions> refreshJwtOptions
|
||||||
, ISqlSugarRepository<RoleEntity> roleRepository)
|
, ISqlSugarRepository<RoleEntity> roleRepository)
|
||||||
{
|
{
|
||||||
_repository = repository;
|
_repository = repository;
|
||||||
@@ -50,7 +50,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
_localEventBus = localEventBus;
|
_localEventBus = localEventBus;
|
||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_roleRepository = roleRepository;
|
_roleRepository = roleRepository;
|
||||||
_refreshJwtOptions= refreshJwtOptions.Value;
|
_refreshJwtOptions = refreshJwtOptions.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -112,11 +112,15 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
return returnToken;
|
return returnToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateRefreshToken()
|
public string CreateRefreshToken(Guid userId)
|
||||||
{
|
{
|
||||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_refreshJwtOptions.SecurityKey));
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_refreshJwtOptions.SecurityKey));
|
||||||
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
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(
|
var token = new JwtSecurityToken(
|
||||||
issuer: _refreshJwtOptions.Issuer,
|
issuer: _refreshJwtOptions.Issuer,
|
||||||
audience: _refreshJwtOptions.Audience,
|
audience: _refreshJwtOptions.Audience,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
|
|||||||
{
|
{
|
||||||
public interface IAccountManager : IDomainService
|
public interface IAccountManager : IDomainService
|
||||||
{
|
{
|
||||||
|
string CreateRefreshToken(Guid userId);
|
||||||
Task<string> GetTokenByUserIdAsync(Guid userId);
|
Task<string> GetTokenByUserIdAsync(Guid userId);
|
||||||
Task LoginValidationAsync(string userName, string password, Action<UserEntity> userAction = null);
|
Task LoginValidationAsync(string userName, string password, Action<UserEntity> userAction = null);
|
||||||
Task RegisterAsync(string userName, string password, long phone);
|
Task RegisterAsync(string userName, string password, long phone);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore
|
|||||||
{
|
{
|
||||||
DataPermissionFilter(sqlSugarClient);
|
DataPermissionFilter(sqlSugarClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
base.CustomDataFilter(sqlSugarClient);
|
base.CustomDataFilter(sqlSugarClient);
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ namespace Yi.Framework.Rbac.SqlSugarCore
|
|||||||
protected void DataPermissionFilter(ISqlSugarClient sqlSugarClient)
|
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;
|
if (CurrentUser.UserName.Equals(UserConst.Admin) || CurrentUser.Roles.Any(f => f.Equals(UserConst.AdminRolesCode))) return;
|
||||||
var expUser = Expressionable.Create<UserEntity>();
|
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.AspNetCore.Microsoft.Extensions.DependencyInjection;
|
||||||
using Yi.Framework.Bbs.Application;
|
using Yi.Framework.Bbs.Application;
|
||||||
using Yi.Framework.Rbac.Application;
|
using Yi.Framework.Rbac.Application;
|
||||||
|
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
||||||
using Yi.Framework.Rbac.Domain.Shared.Options;
|
using Yi.Framework.Rbac.Domain.Shared.Options;
|
||||||
|
|
||||||
namespace Yi.Abp.Web
|
namespace Yi.Abp.Web
|
||||||
@@ -144,7 +145,7 @@ namespace Yi.Abp.Web
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.AddJwtBearer("Refresh", options => {
|
.AddJwtBearer(TokenTypeConst.Refresh, options => {
|
||||||
options.TokenValidationParameters = new TokenValidationParameters
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
{
|
{
|
||||||
ClockSkew = TimeSpan.Zero,
|
ClockSkew = TimeSpan.Zero,
|
||||||
@@ -153,6 +154,18 @@ namespace Yi.Abp.Web
|
|||||||
ValidAudience = refreshJwtOptions.Audience,
|
ValidAudience = refreshJwtOptions.Audience,
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(refreshJwtOptions.SecurityKey))
|
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 =>
|
.AddQQ(options =>
|
||||||
|
|||||||
Reference in New Issue
Block a user