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

.NET Core Web API如何按来源应用/URL设置Authorize属性

两种可行方案分析

方案一:拆分两个控制器

这种方式逻辑直白,不用额外写复杂的判断逻辑,适合追求清晰隔离的场景。

  • 优点:权限规则完全分离,后期维护时不用在同一个地方处理不同客户端的授权逻辑,出错概率低。
  • 缺点:如果两个客户端的业务逻辑高度重合,会有代码重复问题——不过可以把核心业务抽成独立的服务类,让两个控制器都调用这个服务,就能解决重复问题。

示例代码:
给Angular用的授权控制器:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Route("api/angular/[controller]")]
[ApiController]
public class DataController : ControllerBase
{
    private readonly IDataService _dataService;

    public DataController(IDataService dataService)
    {
        _dataService = dataService;
    }

    [HttpGet]
    public IActionResult GetData()
    {
        var data = _dataService.GetBusinessData();
        return Ok(data);
    }
}

给WPF用的无授权控制器:

[AllowAnonymous]
[Route("api/wpf/[controller]")]
[ApiController]
public class DataController : ControllerBase
{
    private readonly IDataService _dataService;

    public DataController(IDataService dataService)
    {
        _dataService = dataService;
    }

    [HttpGet]
    public IActionResult GetData()
    {
        var data = _dataService.GetBusinessData();
        return Ok(data);
    }
}

抽离的业务服务类:

public interface IDataService
{
    object GetBusinessData();
}

public class DataService : IDataService
{
    public object GetBusinessData()
    {
        // 实际业务逻辑
        return new { Content = "业务数据内容" };
    }
}

方案二:自定义授权属性判断请求来源

可以在同一个控制器里处理两种客户端的请求,通过识别请求来源来决定是否校验JWT。

实现步骤

  1. 定义自定义授权要求和处理逻辑:
public class ClientAuthRequirement : IAuthorizationRequirement
{
}

public class ClientAuthHandler : AuthorizationHandler<ClientAuthRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ClientAuthRequirement requirement)
    {
        if (context.Resource is not HttpContext httpContext)
        {
            context.Fail();
            return Task.CompletedTask;
        }

        // 从请求头获取客户端标识(需要WPF和Angular在请求时主动携带)
        var clientType = httpContext.Request.Headers["X-Client-Type"].FirstOrDefault();

        // WPF客户端直接放行
        if (clientType == "WPF")
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        // Angular客户端校验JWT是否有效
        if (clientType == "Angular" && context.User.Identity?.IsAuthenticated == true)
        {
            context.Succeed(requirement);
            return Task.CompletedTask;
        }

        // 其他情况拒绝访问
        context.Fail();
        return Task.CompletedTask;
    }
}
  1. 在Program.cs中注册授权服务:
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ClientSpecificAuth", policy =>
        policy.AddRequirements(new ClientAuthRequirement()));
});

builder.Services.AddScoped<IAuthorizationHandler, ClientAuthHandler>();
  1. 控制器上应用自定义策略:
[Authorize(Policy = "ClientSpecificAuth")]
[Route("api/[controller]")]
[ApiController]
public class DataController : ControllerBase
{
    private readonly IDataService _dataService;

    public DataController(IDataService dataService)
    {
        _dataService = dataService;
    }

    [HttpGet]
    public IActionResult GetData()
    {
        var data = _dataService.GetBusinessData();
        return Ok(data);
    }
}

注意事项

  • 仅靠请求头判断客户端有被伪造的风险,如果对安全性要求高,建议给WPF客户端额外加一种轻量认证方式(比如API密钥),同时校验X-Client-Type和请求头里的API密钥,提升安全性。
  • 这种方案的优势是不用拆分控制器,业务逻辑集中;缺点是授权逻辑相对复杂,后续新增客户端时需要修改授权处理代码。

总结

  • 追求简单清晰、低耦合:选拆分控制器的方案,配合业务服务抽离,代码维护成本低。
  • 希望业务逻辑集中、不想多写控制器:选自定义授权属性方案,但要做好安全校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:15:37