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

如何为ASP.NET Core 3.0 API配置自建OAuth2 Bearer令牌?

从Laravel Passport转到ASP.NET Core 3.0 Web API:轻量化身份验证方案

别担心,我之前刚帮朋友完成过类似的迁移,Laravel Passport的核心是密码授权+JWT令牌,在ASP.NET Core里用原生的Identity+JWT就能实现完全一致的功能,而且轻量化,完全不需要IdentityServer4(确实太重型了,没必要)。下面给你一个初学者友好的分步指南:

一、核心依赖包(NuGet安装)

这些都是微软官方包,稳定且文档齐全:

  • Microsoft.AspNetCore.Identity.EntityFrameworkCore:用户管理(注册、登录、密码哈希)+ EF Core集成
  • Microsoft.AspNetCore.Authentication.JwtBearer:JWT令牌的验证支持
  • Microsoft.EntityFrameworkCore.SqlServer:如果你用SQL Server(用其他数据库的话换对应驱动,比如MySQL就装Microsoft.EntityFrameworkCore.MySql)

二、分步配置与实现

1. 配置Identity和数据库上下文

首先创建你的DbContext,继承自IdentityDbContext(它自带了用户、角色等基础表):

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

public class AppDbContext : IdentityDbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}

然后在Startup.cs的ConfigureServices里注册服务:

public void ConfigureServices(IServiceCollection services)
{
    // 注册数据库上下文
    services.AddDbContext<AppDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    // 配置Identity(用户管理)
    services.AddIdentity<IdentityUser, IdentityRole>()
        .AddEntityFrameworkStores<AppDbContext>()
        .AddDefaultTokenProviders();

    // 自定义密码规则,可匹配Laravel Passport的要求
    services.Configure<IdentityOptions>(options =>
    {
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireUppercase = true;
        options.Password.RequireNonAlphanumeric = false; // 可选,按需调整
        options.Password.RequiredLength = 8;
    });
}

2. 配置JWT认证

继续在ConfigureServices里添加JWT的配置:

// 配置JWT认证
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 = Configuration["Jwt:Issuer"],
        ValidAudience = Configuration["Jwt:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
    };
});

别忘了在appsettings.json里添加JWT的配置项:

"Jwt": {
  "Key": "YourSuperSecretKey_AtLeast16Characters_LikeThisOne",
  "Issuer": "https://your-api-domain.com", // 替换为你的API地址
  "Audience": "https://your-api-domain.com"
}

最后在Startup.cs的Configure方法里启用认证和授权:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 其他中间件(如UseRouting、UseEndpoints)之前添加
    app.UseAuthentication();
    app.UseAuthorization();

    // ... 其他配置
}

3. 编写认证接口(登录/注册)

创建一个AuthController,处理用户注册和登录,生成JWT令牌:

using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IConfiguration _configuration;

    public AuthController(UserManager<IdentityUser> userManager, IConfiguration configuration)
    {
        _userManager = userManager;
        _configuration = configuration;
    }

    // 注册接口
    [HttpPost("register")]
    public async Task<IActionResult> Register([FromBody] RegisterModel model)
    {
        var user = new IdentityUser { UserName = model.Email, Email = model.Email };
        var result = await _userManager.CreateAsync(user, model.Password);

        if (result.Succeeded)
        {
            return Ok(new { Message = "User registered successfully" });
        }

        return BadRequest(result.Errors);
    }

    // 登录接口(生成JWT)
    [HttpPost("login")]
    public async Task<IActionResult> Login([FromBody] LoginModel model)
    {
        var user = await _userManager.FindByEmailAsync(model.Email);
        if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
        {
            // 生成JWT的Claims(可自定义添加用户ID、角色等信息)
            var claims = new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, user.Email),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(ClaimTypes.NameIdentifier, user.Id)
            };

            // 签名密钥
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            // 创建令牌
            var token = new JwtSecurityToken(
                issuer: _configuration["Jwt:Issuer"],
                audience: _configuration["Jwt:Audience"],
                claims: claims,
                expires: DateTime.Now.AddDays(7), // 令牌有效期,按需调整
                signingCredentials: creds);

            return Ok(new
            {
                token = new JwtSecurityTokenHandler().WriteToken(token),
                expiration = token.ValidTo
            });
        }

        return Unauthorized(new { Message = "Invalid email or password" });
    }
}

// 辅助模型类
public class RegisterModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}

public class LoginModel
{
    public string Email { get; set; }
    public string Password { get; set; }
}

4. 保护API端点

在需要授权访问的Controller或Action上添加[Authorize]属性即可,比如:

[Route("api/[controller]")]
[ApiController]
[Authorize] // 需携带有效JWT才能访问此接口
public class ProtectedController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok(new { Message = "This is a protected endpoint", UserId = User.FindFirstValue(ClaimTypes.NameIdentifier) });
    }
}

5. 初始化数据库

打开Package Manager Console,执行以下EF迁移命令创建用户表:

Add-Migration InitialIdentity
Update-Database

三、前端JS框架对接

和Laravel Passport的用法几乎一致:

  1. 用户输入邮箱密码,调用/api/auth/login接口,拿到返回的token。
  2. 将token存储在localStorage或sessionStorage中。
  3. 之后每次请求API时,在请求头里添加:
    headers: {
      'Authorization': `Bearer ${token}`
    }
    
    (以Axios为例,其他框架逻辑类似)

四、关键注意事项

  • 密钥安全性:生产环境中Jwt:Key不要硬编码,用环境变量或Secret Manager管理。
  • HTTPS:生产环境必须使用HTTPS,防止令牌被劫持。
  • 令牌有效期:根据业务需求调整expires时间,短有效期可配合刷新令牌(如需可后续扩展)。
  • 自定义用户字段:若需额外用户信息(如昵称、头像),可创建ApplicationUser继承IdentityUser,添加自定义属性后修改DbContext和Identity的注册。

这个方案完全对应Laravel Passport的密码授权模式,轻量、易维护,适合初学者上手,完全不需要引入IdentityServer4的复杂配置。

内容的提问来源于stack exchange,提问作者user5405648

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 19:07:41