如何基于ASPNETUSERS表实现ASP.NET Core 6用户认证及JWT委托流
ASP.NET Core 6 + Azure SQL + JWT认证 + On-Behalf-Of委托流实现方案
1. 配置Identity与Azure SQL连接
先安装必要依赖包:
Microsoft.AspNetCore.Identity.EntityFrameworkCoreMicrosoft.EntityFrameworkCore.SqlServerMicrosoft.EntityFrameworkCore.Tools(用于数据库迁移)
1.1 定义数据库上下文
创建继承自IdentityDbContext的上下文类,关联Azure SQL中的Identity表:
public class AppDbContext : IdentityDbContext<IdentityUser> { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } }
1.2 配置连接与Identity服务
在appsettings.json中添加Azure SQL连接字符串:
{ "ConnectionStrings": { "DefaultConnection": "Server=tcp:[你的Azure SQL服务器名].database.windows.net,1433;Initial Catalog=[数据库名];Persist Security Info=False;User ID=[用户名];Password=[密码];MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" }, "JwtSettings": { "Issuer": "https://your-api-domain.com", "Audience": "https://your-api-domain.com", "SecretKey": "your-strong-symmetric-secret-key-at-least-16-chars" } }
在Program.cs中注册DbContext与Identity服务:
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddIdentity<IdentityUser, IdentityRole>() .AddEntityFrameworkStores<AppDbContext>() .AddDefaultTokenProviders();
2. 实现用户登录认证与JWT生成
2.1 配置JWT认证服务
在Program.cs中添加JWT认证配置:
builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["JwtSettings:Issuer"], ValidAudience = builder.Configuration["JwtSettings:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:SecretKey"])) }; }); builder.Services.AddAuthorization();
2.2 编写登录API接口
创建AuthController实现登录逻辑,验证用户并生成JWT:
[ApiController] [Route("api/auth")] public class AuthController : ControllerBase { private readonly UserManager<IdentityUser> _userManager; private readonly SignInManager<IdentityUser> _signInManager; private readonly IConfiguration _configuration; public AuthController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, IConfiguration configuration) { _userManager = userManager; _signInManager = signInManager; _configuration = configuration; } [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginRequest request) { var user = await _userManager.FindByNameAsync(request.Username); if (user == null || !await _userManager.CheckPasswordAsync(user, request.Password)) { return Unauthorized("用户名或密码错误"); } var authClaims = new List<Claim> { new Claim(ClaimTypes.Name, user.UserName), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(ClaimTypes.NameIdentifier, user.Id) }; // 添加用户角色 var userRoles = await _userManager.GetRolesAsync(user); foreach (var role in userRoles) { authClaims.Add(new Claim(ClaimTypes.Role, role)); } var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtSettings:SecretKey"])); var token = new JwtSecurityToken( issuer: _configuration["JwtSettings:Issuer"], audience: _configuration["JwtSettings:Audience"], expires: DateTime.Now.AddHours(3), claims: authClaims, signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256) ); return Ok(new { Token = new JwtSecurityTokenHandler().WriteToken(token), Expiration = token.ValidTo }); } public class LoginRequest { public string Username { get; set; } public string Password { get; set; } } }
3. 配置On-Behalf-Of(OBO)委托流对接下游API
OBO流用于将用户身份委托给当前服务,以用户身份请求下游API,依赖Microsoft.Identity.Web包。
3.1 Azure AD应用注册配置
- 在Azure AD中注册两个应用:当前API应用和下游API应用
- 向下游API应用添加API范围(例如
api://[下游API ClientId]/access_as_user) - 在当前API应用中添加下游API的委托权限,完成管理员同意
- 记录当前API的
TenantId、ClientId、ClientSecret,以及下游API的范围
3.2 配置OBO服务与认证
在appsettings.json中添加Azure AD配置:
{ "AzureAd": { "Instance": "https://login.microsoftonline.com/", "TenantId": "你的Azure AD租户ID", "ClientId": "当前API的ClientId", "ClientSecret": "当前API的ClientSecret", "Scopes": "api://[下游API ClientId]/access_as_user" } }
在Program.cs中更新认证配置,启用OBO流:
// 替换原有JWT认证配置,改用Microsoft.Identity.Web builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration) .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); // 注册HttpClient用于调用下游API builder.Services.AddHttpClient();
3.3 实现下游API调用
在需要调用下游API的控制器中,注入ITokenAcquisition和HttpClient,获取委托Token并发起请求:
[ApiController] [Route("api/downstream")] [Authorize] public class DownstreamApiController : ControllerBase { private readonly ITokenAcquisition _tokenAcquisition; private readonly HttpClient _httpClient; private readonly IConfiguration _configuration; public DownstreamApiController(ITokenAcquisition tokenAcquisition, HttpClient httpClient, IConfiguration configuration) { _tokenAcquisition = tokenAcquisition; _httpClient = httpClient; _configuration = configuration; } [HttpGet] public async Task<IActionResult> CallDownstreamApi() { // 获取下游API的访问Token var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { _configuration["AzureAd:Scopes"] }); // 调用下游API _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var response = await _httpClient.GetAsync("https://your-downstream-api-url/api/data"); if (!response.IsSuccessStatusCode) { return StatusCode((int)response.StatusCode, await response.Content.ReadAsStringAsync()); } var data = await response.Content.ReadFromJsonAsync<DownstreamResponse>(); return Ok(data); } public class DownstreamResponse { // 根据下游API返回结构定义 public string Content { get; set; } } }
关键注意事项
- 执行EF迁移命令创建Identity表:
Add-Migration InitialCreate、Update-Database - JWT的
SecretKey建议存入Azure Key Vault,避免硬编码 - 下游API需配置JWT认证,验证来自当前API的委托Token
- OBO流仅支持委托权限,需确保Azure AD应用权限配置正确
内容的提问来源于stack exchange,提问作者Ramesh S
相关产品推荐
相关产品推荐

