如何为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的用法几乎一致:
- 用户输入邮箱密码,调用
/api/auth/login接口,拿到返回的token。 - 将
token存储在localStorage或sessionStorage中。 - 之后每次请求API时,在请求头里添加:
(以Axios为例,其他框架逻辑类似)headers: { 'Authorization': `Bearer ${token}` }
四、关键注意事项
- 密钥安全性:生产环境中
Jwt:Key不要硬编码,用环境变量或Secret Manager管理。 - HTTPS:生产环境必须使用HTTPS,防止令牌被劫持。
- 令牌有效期:根据业务需求调整
expires时间,短有效期可配合刷新令牌(如需可后续扩展)。 - 自定义用户字段:若需额外用户信息(如昵称、头像),可创建
ApplicationUser继承IdentityUser,添加自定义属性后修改DbContext和Identity的注册。
这个方案完全对应Laravel Passport的密码授权模式,轻量、易维护,适合初学者上手,完全不需要引入IdentityServer4的复杂配置。
内容的提问来源于stack exchange,提问作者user5405648
相关产品推荐
相关产品推荐

