非.NET Core的ASP.NET Web API集成JWT并支持[Authorize]属性方案
ASP.NET Web API(非.NET Core)JWT身份验证完整实现方案
一、必要NuGet包
安装兼容.NET Framework的System.IdentityModel.Tokens.Jwt包(推荐v5.x系列,避免选择.NET Core专属版本)
二、配置JWT参数
在Web.config中添加配置节点,统一管理密钥、发行方、受众等核心参数:
<appSettings> <add key="JwtIssuer" value="your-custom-issuer" /> <add key="JwtAudience" value="your-target-audience" /> <add key="JwtSecretKey" value="your-32-character-256-bit-secret-key" /> </appSettings>
三、实现JWT认证过滤器
创建继承自AuthorizationFilterAttribute的过滤器,自动处理请求中的JWT验证逻辑:
using System; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Net; using System.Net.Http; using System.Security.Claims; using System.Text; using System.Web; using System.Web.Http.Controllers; using System.Web.Http.Filters; using Microsoft.IdentityModel.Tokens; public class JwtAuthenticationFilter : AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { // 跳过标记了[AllowAnonymous]的方法 if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any()) { base.OnAuthorization(actionContext); return; } // 从请求头提取Bearer Token var authHeader = actionContext.Request.Headers.Authorization; if (authHeader == null || !authHeader.Scheme.Equals("Bearer", StringComparison.OrdinalIgnoreCase)) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "缺少有效Bearer Token"); return; } var token = authHeader.Parameter; try { var tokenHandler = new JwtSecurityTokenHandler(); var secretKey = Encoding.ASCII.GetBytes(HttpContext.Current.Application["JwtSecretKey"].ToString()); tokenHandler.ValidateToken(token, new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(secretKey), ValidateIssuer = true, ValidIssuer = HttpContext.Current.Application["JwtIssuer"].ToString(), ValidateAudience = true, ValidAudience = HttpContext.Current.Application["JwtAudience"].ToString(), ValidateLifetime = true, ClockSkew = TimeSpan.Zero // 严格验证过期时间,关闭时间偏移容忍 }, out SecurityToken validatedToken); // 将验证后的用户声明注入请求上下文 var jwtToken = (JwtSecurityToken)validatedToken; var claimsIdentity = new ClaimsIdentity(jwtToken.Claims, "Jwt"); actionContext.RequestContext.Principal = new ClaimsPrincipal(claimsIdentity); } catch (SecurityTokenExpiredException) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Token已过期"); } catch (Exception ex) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, $"Token验证失败: {ex.Message}"); } } }
四、注册过滤器(全局/局部)
全局注册(所有API默认启用验证)
在WebApiConfig.cs的Register方法中添加:
public static void Register(HttpConfiguration config) { // 注册JWT认证过滤器 config.Filters.Add(new JwtAuthenticationFilter()); // 常规Web API路由配置 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); }
局部注册(仅指定控制器/方法启用)
直接在控制器或方法上添加[JwtAuthenticationFilter]即可。
五、使用[Authorize]实现身份验证与授权
1. 基础身份验证
添加[Authorize]属性,仅允许携带有效JWT的请求访问:
[Authorize] public class UserController : ApiController { public IHttpActionResult GetCurrentUser() { // 从上下文获取当前用户声明 var userId = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value; var userName = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; return Ok(new { UserId = userId, UserName = userName }); } }
2. 角色授权
如果JWT包含role声明,可通过Roles参数限制指定角色访问:
[Authorize(Roles = "Admin,Supervisor")] public IHttpActionResult DeleteUser(int id) { // 仅Admin/Supervisor角色可调用 return Ok("用户删除成功"); }
3. 自定义声明授权
基于自定义声明实现权限控制,比如验证用户是否拥有特定操作权限:
public class PermissionAuthorizeAttribute : AuthorizeAttribute { private readonly string _permission; public PermissionAuthorizeAttribute(string permission) { _permission = permission; } protected override bool IsAuthorized(HttpActionContext actionContext) { return actionContext.RequestContext.Principal?.Claims.Any(c => c.Type == "Permission" && c.Value == _permission) ?? false; } } // 使用示例 [PermissionAuthorize("ManageUsers")] public IHttpActionResult UpdateUser(UserModel model) { // 仅拥有ManageUsers权限的用户可调用 return Ok("用户信息更新成功"); }
六、生成合规JWT示例
生成Token时需包含必要声明(用户ID、角色、自定义权限等):
public string GenerateJwtToken(string userId, string userName, string[] roles, string[] permissions) { var secretKey = Encoding.ASCII.GetBytes(HttpContext.Current.Application["JwtSecretKey"].ToString()); var tokenHandler = new JwtSecurityTokenHandler(); var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, userId), new Claim(ClaimTypes.Name, userName) }; // 添加角色声明 foreach (var role in roles) { claims.Add(new Claim(ClaimTypes.Role, role)); } // 添加自定义权限声明 foreach (var permission in permissions) { claims.Add(new Claim("Permission", permission)); } var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Expires = DateTime.UtcNow.AddHours(2), Issuer = HttpContext.Current.Application["JwtIssuer"].ToString(), Audience = HttpContext.Current.Application["JwtAudience"].ToString(), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(secretKey), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); }
七、注意事项
- 密钥必须满足算法要求:HmacSha256需要至少256位(32个字符)的密钥,避免使用弱密钥。
- 生产环境禁止硬编码密钥,建议使用加密配置项或专业密钥管理服务。
- 可根据业务需求调整Token过期时间,同时考虑实现Token刷新机制。
- 匿名访问的方法必须添加
[AllowAnonymous]属性,避免被过滤器拦截。
内容的提问来源于stack exchange,提问作者youselry
相关产品推荐
相关产品推荐

