You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于ASPNETUSERS表实现ASP.NET Core 6用户认证及JWT委托流

ASP.NET Core 6 + Azure SQL + JWT认证 + On-Behalf-Of委托流实现方案

1. 配置Identity与Azure SQL连接

先安装必要依赖包:

  • Microsoft.AspNetCore.Identity.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:37:46