ASP.NET Core MVC如何通过独立API实现用户认证授权?
完全可以这么做,这种架构能有效解耦认证逻辑和业务系统,还能实现用户数据的统一管理,下面分两部分讲具体实现方式:
一、ASP.NET Core MVC 项目配置(调用独立API完成认证)
1. 自定义登录逻辑
放弃默认Identity直接连接数据库的方式,在登录接口中调用独立认证API验证用户凭证,接收返回的身份信息后生成用户身份并完成登录。
示例代码(AccountController的Login POST方法):
using System.Security.Claims; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using System.Net.Http.Json; [HttpPost] public async Task<IActionResult> Login(LoginViewModel model) { if (!ModelState.IsValid) return View(model); // 注入HttpClientFactory创建客户端 var httpClient = _httpClientFactory.CreateClient(); var loginPayload = new { Username = model.Username, Password = model.Password }; // 调用认证API var response = await httpClient.PostAsJsonAsync("https://your-auth-api-domain/api/auth/login", loginPayload); if (!response.IsSuccessStatusCode) { ModelState.AddModelError("", "用户名或密码错误"); return View(model); } // 解析API返回的认证结果 var authResult = await response.Content.ReadFromJsonAsync<AuthResult>(); // 构建用户Claims身份 var claims = new List<Claim> { new Claim(ClaimTypes.Name, authResult.Username), new Claim(ClaimTypes.Role, authResult.Role) // 按需添加其他用户属性作为Claim }; var identity = new ClaimsIdentity(claims, "CustomApiAuth"); var userPrincipal = new ClaimsPrincipal(identity); // 将用户身份保存到Cookie,完成登录 await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties { IsPersistent = model.RememberMe, ExpiresUtc = DateTimeOffset.UtcNow.AddHours(2) }); return RedirectToAction("Index", "Profile"); }
2. 基础配置
- 在Program.cs中注册HttpClientFactory和Cookie认证:
// 注册HttpClient工厂 builder.Services.AddHttpClient(); // 配置Cookie认证 builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/Login"; // 未登录时跳转的登录页 options.AccessDeniedPath = "/Account/AccessDenied"; // 权限不足跳转页 }); // 启用认证和授权中间件(注意顺序:先认证后授权) app.UseAuthentication(); app.UseAuthorization();
3. 授权保护页面
在需要授权的Controller或Action上添加[Authorize]特性即可:
[Authorize] public class ProfileController : Controller { public IActionResult Index() { // 这里可以通过User.Claims获取用户身份信息 return View(); } }
二、独立认证API的实现
1. 核心认证流程
API需要完成以下步骤:
- 接收前端(MVC项目)传来的用户名和密码
- 连接独立用户数据库验证凭证合法性
- 验证通过后生成身份凭证(比如JWT令牌)或返回用户身份信息
- 向MVC项目返回认证结果(成功/失败+对应数据)
2. API示例代码
以ASP.NET Core Web API为例,实现登录接口:
首先定义统一的请求/返回模型:
// 登录请求模型 public class LoginRequest { public string Username { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; } // 认证结果返回模型 public class AuthResult { public string Username { get; set; } = string.Empty; public string Role { get; set; } = string.Empty; public string Token { get; set; } = string.Empty; public int ExpiresIn { get; set; } // 令牌有效期(秒) }
然后实现AuthController:
using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; [ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly IUserRepository _userRepo; private readonly IConfiguration _config; public AuthController(IUserRepository userRepo, IConfiguration config) { _userRepo = userRepo; _config = config; } [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginRequest request) { // 从独立数据库查询用户 var user = await _userRepo.GetUserByUsername(request.Username); if (user == null || !VerifyPassword(request.Password, user.PasswordHash)) { return Unauthorized(new { Message = "用户名或密码错误" }); } // 生成JWT令牌 var jwtToken = GenerateJwtToken(user); return Ok(new AuthResult { Username = user.Username, Role = user.Role, Token = jwtToken, ExpiresIn = 7200 // 2小时 }); } // 生成JWT令牌方法 private string GenerateJwtToken(User user) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.Username), new Claim(ClaimTypes.Role, user.Role) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: _config["Jwt:Issuer"], audience: _config["Jwt:Audience"], claims: claims, expires: DateTime.Now.AddHours(2), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } // 密码验证(这里用BCrypt哈希验证,需安装BCrypt.Net NuGet包) private bool VerifyPassword(string inputPassword, string storedHash) { return BCrypt.Net.BCrypt.Verify(inputPassword, storedHash); } }
3. API数据库配置
实现IUserRepository接口,连接独立服务器的数据库(比如用EF Core):
public class UserRepository : IUserRepository { private readonly UserDbContext _dbContext; public UserRepository(UserDbContext dbContext) { _dbContext = dbContext; } public async Task<User> GetUserByUsername(string username) { return await _dbContext.Users.FirstOrDefaultAsync(u => u.Username == username); } }
在API的Program.cs中配置数据库连接字符串:
builder.Services.AddDbContext<UserDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("UserDatabase"))); // 注册仓储 builder.Services.AddScoped<IUserRepository, UserRepository>();
三、关键注意事项
- 通信安全:MVC项目和认证API之间必须用HTTPS通信,防止密码、令牌等敏感数据被窃取。
- 令牌存储:MVC项目推荐将JWT令牌存储在HttpOnly Cookie中,避免XSS攻击。
- 权限扩展:如果需要细粒度权限控制,可以在API中新增权限验证接口,MVC项目调用该接口判断用户是否具备操作权限。
内容的提问来源于stack exchange,提问作者Nina
相关产品推荐
相关产品推荐

