You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 13:42:12