121 lines
4.3 KiB
C#
121 lines
4.3 KiB
C#
using YD_Event.Application.Auth.Dtos;
|
||
|
||
namespace YD_Event.Application.Auth;
|
||
/// <summary>
|
||
/// 用户授权
|
||
/// </summary>
|
||
[AllowAnonymous]
|
||
public class AuthService : IDynamicApiController
|
||
{
|
||
private readonly ISqlSugarRepository<SysUser> _sysUseRepository;
|
||
private readonly ICaptcha _captcha;
|
||
private readonly IIdGenerator _idGenerator;
|
||
private readonly IEasyCachingProvider _easyCachingProvider;
|
||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||
|
||
public AuthService(ISqlSugarRepository<SysUser> sysUseRepository,
|
||
ICaptcha captcha,
|
||
IIdGenerator idGenerator,
|
||
IEasyCachingProvider easyCachingProvider,
|
||
IHttpContextAccessor httpContextAccessor)
|
||
{
|
||
_sysUseRepository = sysUseRepository;
|
||
_captcha = captcha;
|
||
_idGenerator = idGenerator;
|
||
_easyCachingProvider = easyCachingProvider;
|
||
_httpContextAccessor = httpContextAccessor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 系统用户登录
|
||
/// </summary>
|
||
/// <param name="dto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task SignIn(AdminLoginInput dto)
|
||
{
|
||
bool validate = _captcha.Validate(dto.Id, dto.Code);
|
||
if (!validate)
|
||
{
|
||
throw Oops.Bah("验证码错误");
|
||
}
|
||
|
||
string signInErrorCacheKey = $"login.error.{dto.Account}";
|
||
CacheValue<int> value = await _easyCachingProvider.GetAsync<int>(signInErrorCacheKey);
|
||
//5分钟内连续验证密码失败超过4次将限制用户尝试
|
||
if (value.HasValue && value.Value > 4)
|
||
{
|
||
throw Oops.Bah("由于您多次登录失败,系统已限制账户登录");
|
||
}
|
||
SysUser user = await _sysUseRepository.GetFirstAsync(x => x.Account == dto.Account);
|
||
if (user == null)
|
||
{
|
||
throw Oops.Bah("用户名或密码错误");
|
||
}
|
||
|
||
var context = _httpContextAccessor.HttpContext;
|
||
if (user.Status == AvailabilityStatus.Disable || (user.LockExpired.HasValue && DateTime.Now < user.LockExpired))
|
||
{
|
||
throw Oops.Bah("您的账号被锁定");
|
||
}
|
||
|
||
if (user.Password != MD5Encryption.Encrypt($"{_idGenerator.Encode(user.Id)}{dto.Password}"))
|
||
{
|
||
await _easyCachingProvider.SetAsync(signInErrorCacheKey, value.Value + 1, TimeSpan.FromMinutes(5));
|
||
throw Oops.Bah("用户名或密码错误");
|
||
}
|
||
long uniqueId = _idGenerator.NewLong();
|
||
string token = JWTEncryption.Encrypt(new Dictionary<string, object>()
|
||
{
|
||
[AuthClaimsConst.AuthIdKey] = user.Id,
|
||
[AuthClaimsConst.AccountKey] = user.Account,
|
||
[AuthClaimsConst.UuidKey] = uniqueId,
|
||
[AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.Manager
|
||
},100000);
|
||
// 获取刷新 token
|
||
var refreshToken = JWTEncryption.GenerateRefreshToken(token);
|
||
// 设置响应报文头
|
||
context.SigninToSwagger(token);
|
||
context!.Response.Headers["access-token"] = token;
|
||
context.Response.Headers["x-access-token"] = refreshToken;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取验证码
|
||
/// </summary>
|
||
/// <param name="id">验证码唯一id</param>
|
||
/// <returns></returns>
|
||
[HttpGet]
|
||
public IActionResult Captcha([FromQuery] string id)
|
||
{
|
||
var data = _captcha.Generate(id);
|
||
var stream = new MemoryStream(data.Bytes);
|
||
return new FileStreamResult(stream, "image/gif");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新Token
|
||
/// </summary>
|
||
/// <param name="accessToken"></param>
|
||
/// <returns></returns>
|
||
[HttpPost("refresh")]
|
||
public string RefreshToken([FromQuery] string accessToken)
|
||
{
|
||
var context = _httpContextAccessor.HttpContext;
|
||
var refreshToken = context.Request.Headers["x-access-token"].ToString();
|
||
|
||
if (string.IsNullOrWhiteSpace(accessToken) || string.IsNullOrWhiteSpace(refreshToken))
|
||
{
|
||
throw Oops.Bah("无效的Token");
|
||
}
|
||
|
||
// 交换新的 Token
|
||
var newToken = JWTEncryption.Exchange(accessToken, refreshToken);
|
||
|
||
// 设置响应报文头
|
||
context.Response.Headers["access-token"] = newToken;
|
||
context.Response.Headers["x-access-token"] = refreshToken; // 刷新Token通常保持不变,或者也可以轮换
|
||
|
||
return newToken;
|
||
}
|
||
} |