在無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中文網其他相關文章!