在无OWIN中间件的ASP.NET Web API中实现JWT身份验证
本文介绍如何在旧版ASP.NET Web API中,无需OWIN中间件即可实现JWT身份验证。核心原理是颁发JWT令牌并在收到请求时验证它们。
令牌生成端点
提供一个令牌端点,用户可以在该端点获取JWT令牌,例如使用控制器操作的简单实现:
<code class="language-csharp">public class TokenController : ApiController { [AllowAnonymous] public string Get(string username, string password) { if (CheckUser(username, password)) { return JwtManager.GenerateToken(username); } throw new HttpResponseException(HttpStatusCode.Unauthorized); } private bool CheckUser(string username, string password) { // 应在数据库中进行检查 return true; // 此处应替换为实际的用户验证逻辑 } }</code>
使用System.IdentityModel.Tokens.Jwt生成令牌
使用System.IdentityModel.Tokens.Jwt NuGet包和HMACSHA256对称密钥生成令牌:
<code class="language-csharp">/// <summary> /// 使用以下代码生成对称密钥 /// var hmac = new HMACSHA256(); /// var key = Convert.ToBase64String(hmac.Key); /// </summary> private const string Secret = "db3OIsj+BXE9NZDy0t8W3TcNekrF+2d/1sFnWG4HnV8TZY30iTOdtVWJG8abWvB1GlOgJuQZdcF2Luqm/hccMw=="; public static string GenerateToken(string username, int expireMinutes = 20) { var symmetricKey = Convert.FromBase64String(Secret); var tokenHandler = new JwtSecurityTokenHandler(); var now = DateTime.UtcNow; var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, username) }), Expires = now.AddMinutes(expireMinutes), SigningCredentials = new SigningCredentials( new SymmetricSecurityKey(symmetricKey), SecurityAlgorithms.HmacSha256Signature) }; var stoken = tokenHandler.CreateToken(tokenDescriptor); var token = tokenHandler.WriteToken(stoken); return token; }</code>
使用身份验证过滤器进行JWT验证
为了进行JWT验证,创建一个继承自IAuthenticationFilter
的自定义身份验证过滤器:
<code class="language-csharp">public class ValueController : ApiController { [JwtAuthentication] // 自定义过滤器属性 public string Get() { return "value"; } }</code>
在身份验证过滤器中,实现验证逻辑并返回ClaimsPrincipal
:
<code class="language-csharp">protected Task<IPrincipal> AuthenticateJwtToken(string token) { string username; if (ValidateToken(token, out username)) { // 基于用户名,从数据库获取更多信息以构建本地标识 var claims = new List<Claim> { new Claim(ClaimTypes.Name, username) // 根据需要添加更多声明:角色等 }; var identity = new ClaimsIdentity(claims, "Jwt"); IPrincipal user = new ClaimsPrincipal(identity); return Task.FromResult(user); } return Task.FromResult<IPrincipal>(null); }</code>
使用JWT库进行JWT验证
为了验证JWT令牌并获取ClaimsPrincipal
,可以使用JWT库:
<code class="language-csharp">public static ClaimsPrincipal GetPrincipal(string token) { try { var tokenHandler = new JwtSecurityTokenHandler(); var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken; if (jwtToken == null) return null; var symmetricKey = Convert.FromBase64String(Secret); var validationParameters = new TokenValidationParameters() { RequireExpirationTime = true, ValidateIssuer = false, ValidateAudience = false, IssuerSigningKey = new SymmetricSecurityKey(symmetricKey) }; SecurityToken securityToken; var principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken); return principal; } catch (Exception) { // 应写入日志 return null; } }</code>
授权
为了防止匿名请求,添加以下全局配置:
<code class="language-csharp">config.Filters.Add(new AuthorizeAttribute());</code>
Postman测试
使用Postman请求令牌:
<code>GET http://localhost:{port}/api/token?username=cuong&password=1</code>
在授权请求的标头中使用获取的JWT令牌:
<code>GET http://localhost:{port}/api/value Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6ImN1b25nIiwibmJmIjoxNDc3NTY1MjU4LCJleHAiOjE0Nzc1NjY0NTgsImlhdCI6MTQ3NzU2NTI1OH0.dSwwufd4-gztkLpttZsZ1255oEzpWCJkayR_4yvNL1s</code>
请注意,代码中的CheckUser
方法和错误处理部分需要根据实际应用进行完善。 Secret
密钥也应该存储在更安全的地方,而不是直接硬编码在代码中。 这只是一个简化的示例,实际应用中需要考虑更全面的安全性和错误处理机制。
以上是如何在没有 OWIN 中间件的情况下在 ASP.NET Web API 中实现 JWT 身份验证?的详细内容。更多信息请关注PHP中文网其他相关文章!