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

.NET Core如何识别JWT请求来自Postman还是浏览器并实现鉴权

识别Postman请求与浏览器请求的核心方法

首先明确:不存在100%不可绕过的识别方案,所有请求头都可以被人为伪造,但常规场景下以下方案可以拦截绝大多数直接复制Token用Postman调用的行为:

  • 校验User-Agent请求头:Postman默认发送的User-Agent会携带PostmanRuntime关键字,普通浏览器的UA不会包含该字段
  • 校验Referer/Origin请求头:浏览器发起同站业务请求时会自动携带对应站点的Referer/Origin值,直接用Postman发请求默认不会携带正确的业务站点域名的对应字段
  • 校验绑定用户身份的安全Cookie:可以在用户首次访问业务站点时,下发一个和当前用户身份绑定的HttpOnly加密Cookie,JWT校验通过的同时还要校验该Cookie的有效性,Postman就算复制到了Token也无法获取浏览器端的HttpOnly Cookie
.NET Core 实现鉴权逻辑的步骤

第一步:创建自定义授权规则

// 自定义授权要求
public class BrowserOnlyRequirement : IAuthorizationRequirement
{
}

// 授权要求的处理逻辑
public class BrowserOnlyHandler : AuthorizationHandler<BrowserOnlyRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, BrowserOnlyRequirement requirement)
    {
        if (context.Resource is not HttpContext httpContext)
        {
            context.Fail();
            return Task.CompletedTask;
        }

        var request = httpContext.Request;
        
        // 1. 拦截Postman默认UA请求
        var userAgent = request.Headers.UserAgent.ToString();
        if (userAgent.Contains("PostmanRuntime", StringComparison.OrdinalIgnoreCase))
        {
            context.Fail();
            return Task.CompletedTask;
        }

        // 2. 校验Origin是否为业务域名,替换为你自己的站点域名
        var allowedOrigin = "https://你的业务站点域名.com";
        if (request.Headers.TryGetValue("Origin", out var origin) && origin != allowedOrigin)
        {
            context.Fail();
            return Task.CompletedTask;
        }

        // 3. 校验绑定用户身份的安全Cookie
        if (!request.Cookies.TryGetValue("BizAuthCookie", out var bizCookie) || !ValidateBizCookie(bizCookie, context.User))
        {
            context.Fail();
            return Task.CompletedTask;
        }

        context.Succeed(requirement);
        return Task.CompletedTask;
    }

    // Cookie校验逻辑:需要和JWT中的用户身份绑定,比如解密Cookie后和JWT携带的用户ID做匹配
    private bool ValidateBizCookie(string cookieValue, ClaimsPrincipal user)
    {
        var userIdFromJwt = user.FindFirstValue(ClaimTypes.NameIdentifier);
        if (string.IsNullOrEmpty(userIdFromJwt)) return false;
        // 替换为你自己的Cookie解密逻辑,推荐用.NET自带的IDataProtector实现加密解密
        var userIdFromCookie = DecryptBizCookie(cookieValue);
        return userIdFromCookie == userIdFromJwt;
    }

    private string DecryptBizCookie(string cookieValue)
    {
        // 实现你的解密逻辑
        return string.Empty;
    }
}

第二步:注册授权服务

在Program.cs中注册自定义的授权规则和处理程序,确保你已经完成了常规的JWT鉴权配置:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("BrowserOnly", policy =>
    {
        policy.AddRequirements(new BrowserOnlyRequirement());
        policy.RequireAuthenticatedUser(); // 要求JWT校验通过
    });
});

// 注册自定义授权处理程序
builder.Services.AddScoped<IAuthorizationHandler, BrowserOnlyHandler>();

第三步:应用授权策略

在需要保护的接口Controller或者Action上添加授权特性即可:

[Authorize(Policy = "BrowserOnly")]
[ApiController]
[Route("api/[controller]")]
public class BusinessController : ControllerBase
{
    // 你的业务接口
}
注意事项

以上方案只能拦截未篡改请求头的普通Postman调用,无法阻止攻击者手动伪造浏览器请求头、复制对应Cookie发起请求的情况。如果需要更高的安全等级,可以额外叠加前端JS生成的动态请求签名、接口请求频率限制等策略,多层防护降低风险。

内容的提问来源于stack exchange,提问作者Aswin Moothedath

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 13:57:04