使用SQL Server身份验证实现ASP.NET Web API身份认证
完全可行!以下是具体配置步骤
1. 移除原有Windows身份验证配置
首先得把之前的Windows身份验证相关设置清理掉:
- 替换控制器/方法上的
[Authorize(Users = "\\")]为普通的[Authorize](后续我们会用新的认证逻辑来保护接口) - 根据你的.NET版本调整项目配置:
- .NET Core/.NET 6+:在
Program.cs里移除原来的Windows身份验证注册代码(比如AddAuthentication(IISDefaults.AuthenticationScheme)),确保启用匿名认证(因为我们要自己处理登录逻辑) - .NET Framework:在
web.config中关闭Windows身份验证,启用匿名身份验证
- .NET Core/.NET 6+:在
2. 在SQL Server中创建用户存储表
你需要一个表来存储API用户的账号信息(绝对不要存明文密码!),示例SQL脚本如下:
CREATE TABLE ApiUsers ( Id INT PRIMARY KEY IDENTITY(1,1), Username NVARCHAR(50) UNIQUE NOT NULL, PasswordHash NVARCHAR(256) NOT NULL, -- 存储密码的哈希值 Email NVARCHAR(100) NULL )
插入测试用户时,记得用加盐哈希算法(比如BCrypt)生成密码哈希,示例代码(C#):
// 生成密码哈希(比如给用户"testuser"的密码"TestPass123"生成哈希) var passwordHash = BCrypt.Net.BCrypt.HashPassword("TestPass123");
3. 实现认证逻辑(推荐用JWT,API场景最常用)
这里以.NET 6+为例,分步骤配置:
3.1 添加必要的NuGet包
安装Microsoft.AspNetCore.Authentication.JwtBearer和BCrypt.Net-Next(用于密码哈希验证)
3.2 配置JWT参数
在appsettings.json中添加JWT的配置项:
"JwtSettings": { "SecretKey": "your_strong_random_secret_key_here_min_16_chars", "Issuer": "YourApiIssuerName", "Audience": "YourApiAudienceName", "ExpiresInMinutes": 60 }
⚠️ 注意:SecretKey一定要足够长且随机,不要硬编码在代码里,生产环境建议用环境变量或配置中心存储
3.3 注册JWT认证服务
在Program.cs中添加认证和授权服务:
var jwtSettings = builder.Configuration.GetSection("JwtSettings"); // 注册JWT认证 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings["Issuer"], ValidAudience = jwtSettings["Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["SecretKey"])) }; }); // 注册授权服务 builder.Services.AddAuthorization(); // 别忘了添加这两行,启用认证和授权中间件 app.UseAuthentication(); app.UseAuthorization();
3.4 编写登录接口
创建一个允许匿名访问的登录接口,用来验证SQL里的用户并返回JWT令牌:
[ApiController] [Route("api/[controller]")] public class AuthController : ControllerBase { private readonly ApiDbContext _dbContext; private readonly IConfiguration _configuration; public AuthController(ApiDbContext dbContext, IConfiguration configuration) { _dbContext = dbContext; _configuration = configuration; } [AllowAnonymous] [HttpPost("login")] public async Task<IActionResult> Login([FromBody] LoginRequest model) { // 从SQL查询用户 var user = await _dbContext.ApiUsers .FirstOrDefaultAsync(u => u.Username.Equals(model.Username, StringComparison.OrdinalIgnoreCase)); // 验证用户和密码 if (user == null || !BCrypt.Net.BCrypt.Verify(model.Password, user.PasswordHash)) { return Unauthorized("用户名或密码错误"); } // 生成JWT令牌 var token = GenerateJwtToken(user); return Ok(new { AccessToken = token }); } // 生成JWT令牌的辅助方法 private string GenerateJwtToken(ApiUser user) { var jwtSettings = _configuration.GetSection("JwtSettings"); var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), new Claim(ClaimTypes.Name, user.Username) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["SecretKey"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: jwtSettings["Issuer"], audience: jwtSettings["Audience"], claims: claims, expires: DateTime.UtcNow.AddMinutes(Convert.ToDouble(jwtSettings["ExpiresInMinutes"])), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } } // 登录请求模型 public class LoginRequest { public string Username { get; set; } public string Password { get; set; } }
4. 保护API接口
在需要认证才能访问的控制器或方法上添加[Authorize]特性即可,比如:
[ApiController] [Route("api/[controller]")] [Authorize] public class DataController : ControllerBase { // 你的接口逻辑,只有携带有效JWT令牌的请求才能访问 [HttpGet] public IActionResult GetData() { return Ok("这是需要认证才能访问的数据"); } }
5. 测试认证流程
- 调用
POST /api/auth/login接口,传入正确的用户名和密码,获取返回的AccessToken - 在后续请求的
Authorization请求头中添加Bearer {你的AccessToken},即可访问受保护的API接口
可选:简单场景用基本认证
如果你的API场景比较简单,也可以实现基本认证(直接在请求头里传编码后的用户名密码),步骤类似:
- 自定义一个
BasicAuthenticationHandler来验证请求头里的凭证 - 在
Program.cs中注册这个认证方案 - 同样用
[Authorize]保护接口
内容的提问来源于stack exchange,提问作者user3759018
相关产品推荐
相关产品推荐

