如何在Identity中实现用户登录服务并修正JWT认证相关代码
修正ASP.NET Identity登录服务与JWT生成流程(含密码验证)
以下是针对需求的完整代码修正方案,核心实现密码验证→JWT生成的完整流程,同时规范服务接口与逻辑:
1. 定义登录服务接口与结果类
先明确登录服务的契约,避免无意义的空接口:
public interface IUserLogin { // 异步验证用户密码,返回验证结果 Task<LoginValidationResult> ValidateUserCredentials(string userName, string password); } // 自定义登录验证结果,传递验证状态与用户信息 public class LoginValidationResult { public bool IsValid { get; set; } public User? User { get; set; } // 验证成功时返回用户实体 }
2. 修正LoginService实现
修复原方法返回类型错误,正确使用Identity的密码验证逻辑:
public class LoginService : IUserLogin { private readonly SignInManager<User> _signInManager; private readonly UserManager<User> _userManager; // 新增UserManager用于获取用户完整信息 public LoginService(SignInManager<User> signInManager, UserManager<User> userManager) { _signInManager = signInManager; _userManager = userManager; } public async Task<LoginValidationResult> ValidateUserCredentials(string userName, string password) { // 使用Identity原生方法验证密码 var signInResult = await _signInManager.PasswordSignInAsync( userName, password, isPersistent: false, // JWT场景不需要持久化Cookie lockoutOnFailure: false ); if (!signInResult.Succeeded) { return new LoginValidationResult { IsValid = false }; } // 验证成功后获取用户完整实体,用于生成JWT Claims var user = await _userManager.FindByNameAsync(userName); return new LoginValidationResult { IsValid = true, User = user }; } }
3. 改造JWTAuthorizationManager:加入密码验证
原方法直接生成令牌,现在改为先验证密码再生成JWT:
public class JWTAuthorizationManager { private readonly IUserLogin _loginService; private readonly UserManager<User> _userManager; // 通过依赖注入获取登录服务与用户管理器 public JWTAuthorizationManager(IUserLogin loginService, UserManager<User> userManager) { _loginService = loginService; _userManager = userManager; } public async Task<JwtFeilds?> Authenticate(string userName, string password) { // 第一步:验证用户密码 var validationResult = await _loginService.ValidateUserCredentials(userName, password); if (!validationResult.IsValid || validationResult.User == null) { return null; // 验证失败返回null,对应后续未授权 } // 第二步:验证通过,生成JWT令牌 var tokenExpireTimeStamp = DateTime.Now.AddHours(Constants.JWT_TOKEN_EXPIRE_TIME); var jwtHandler = new JwtSecurityTokenHandler(); var tokenKey = Encoding.ASCII.GetBytes(Constants.JWT_SECURITY_KEY_FOR_TOKEN); // 从用户实体动态生成Claims(替代原硬编码内容) var claims = new List<Claim> { new Claim("username", validationResult.User.UserName!), new Claim(ClaimTypes.NameIdentifier, validationResult.User.Id) }; // 可选:添加用户角色到Claims var userRoles = await _userManager.GetRolesAsync(validationResult.User); foreach (var role in userRoles) { claims.Add(new Claim(ClaimTypes.Role, role)); } var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Expires = tokenExpireTimeStamp, SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(tokenKey), SecurityAlgorithms.HmacSha256Signature ) }; var securityToken = jwtHandler.CreateToken(tokenDescriptor); var token = jwtHandler.WriteToken(securityToken); return new JwtFeilds { token = token, user_name = validationResult.User.UserName!, expire_time = (int)tokenExpireTimeStamp.Subtract(DateTime.Now).TotalSeconds }; } }
4. 修正Controller登录接口
改为异步处理,通过依赖注入获取服务,并添加模型验证:
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly JWTAuthorizationManager _jwtManager; // 构造函数注入JWT管理器 public AuthController(JWTAuthorizationManager jwtManager) { _jwtManager = jwtManager; } [HttpPost("login")] public async Task<IActionResult> Login([FromForm] User model) { // 先验证输入模型合法性 if (!ModelState.IsValid) { return BadRequest(ModelState); } var jwtResult = await _jwtManager.Authenticate(model.UserName, model.Password); return jwtResult == null ? Unauthorized() : Ok(jwtResult); } }
5. 注册服务到DI容器
在Program.cs中添加服务注册:
// 注册登录服务 builder.Services.AddScoped<IUserLogin, LoginService>(); // 注册JWT授权管理器 builder.Services.AddScoped<JWTAuthorizationManager>();
内容的提问来源于stack exchange,提问作者sadegh
相关产品推荐
相关产品推荐

