using Application.Domain.Entities; using Application.Models; using Infrastructure.Data; using Infrastructure.Extensions; using Infrastructure.Security; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Security.Claims; namespace UserCenter.Controllers { [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]/[action]")] [ApiController] public class TokenController : ControllerBase { private readonly IConfiguration _cfg; private readonly IRepository _userRepo; private readonly IEncryptionService _encryptionService; public TokenController(IConfiguration cfg, IRepository userRepo, IEncryptionService encryptionService) { this._cfg = cfg; this._userRepo = userRepo; this._encryptionService = encryptionService; } [HttpPost] public ActionResult GetToken([FromBody]LoginModel model) { var success = false; try { var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == model.UserName); if (user == null) { return BadRequest(ModelState.AddModelError("用户名或密码错误")); } else { var maxAccessFailedCount = this._cfg.GetValue("MaxFailedAccessAttemptsBeforeLockout"); var lockoutEndMinutes = this._cfg.GetValue("DefaultAccountLockoutMinutes"); if (user.LockoutEnabled)//对已启用登录锁定的用户,如果当前登录时间超出锁定时间,先解除锁定状态 { if (user.LockoutEnd.HasValue && DateTime.UtcNow > user.LockoutEnd) { user.LockoutEnd = null; user.AccessFailedCount = 0; this._userRepo.SaveChanges(); } } if (user.LockoutEnabled)//对启用登录锁定的用户进行验证 { if (user.LockoutEnd.HasValue == false) { if (user.PasswordHash == this._encryptionService.CreatePasswordHash(model.Password, user.SecurityStamp)) { user.LockoutEnd = null; user.AccessFailedCount = 0; success = true; } else { user.AccessFailedCount += 1; if (user.AccessFailedCount >= maxAccessFailedCount) { user.LockoutEnd = DateTime.UtcNow.AddMinutes(lockoutEndMinutes); return BadRequest(ModelState.AddModelError(o => model.UserName, $"用户被锁定,请于{user.LockoutEnd.Value.ToLocalTime().ToString("HH:mm")}后重试", 1)); } else { return BadRequest(ModelState.AddModelError(o => model.UserName, $"密码错误,再错误{maxAccessFailedCount - user.AccessFailedCount}次后将锁定用户{lockoutEndMinutes}分钟", 2)); } } this._userRepo.SaveChanges(); } } else//对未启用登录锁定的用户进行验证 { if (user.PasswordHash != this._encryptionService.CreatePasswordHash(model.Password, user.SecurityStamp)) { return BadRequest(ModelState.AddModelError("用户名或密码错误")); } } } return Ok(new { AccessToken = Request.HttpContext.GetToken(model.UserName, _cfg, DateTime.Now.AddHours(_cfg.GetValue("AccessTokenHours", 0.5))), RefreshToken = Request.HttpContext.GetToken(model.UserName, _cfg, DateTime.Now.AddHours(_cfg.GetValue("RefreshToken", 720))), }); } catch (Exception ex) { ex.PrintStack(); return Problem(ex.Message); } } [HttpPost] public ActionResult RefreshToken([FromBody][Required]string refreshToken) { try { var token = Request.HttpContext.ReadToken(refreshToken); if (DateTime.UtcNow > token.ValidTo) { return Unauthorized(ModelState.AddModelError("已过期")); } var userName = token.Claims.FirstOrDefault(o => o.Type == ClaimTypes.Name).Value; return Ok(new { AccessToken = Request.HttpContext.GetToken(userName, _cfg, DateTime.Now.AddHours(_cfg.GetValue("AccessTokenHours", 0.5))), RefreshToken = Request.HttpContext.GetToken(userName, _cfg, DateTime.Now.AddHours(_cfg.GetValue("RefreshToken", 720))), }); } catch (Exception ex) { ex.PrintStack(); return Problem(ex.Message); } } } }