对一个特定端点使用不同的授权,.net 核心

Posted

技术标签:

【中文标题】对一个特定端点使用不同的授权,.net 核心【英文标题】:Use different Authorization for one specific endpoint, .net core 【发布时间】:2021-07-09 19:33:40 【问题描述】:

我已通过 Identity Server 4 使用承载方案为我的 Web API 启用身份验证。

在 ConfigureServices 我有:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
            
                options.Authority = identitySetttings.Authority;
                options.Audience = identitySetttings.ApiScope;
                options.RequireHttpsMetadata = false;

在配置中我有:

app.UseAuthentication();
app.UseAuthorization();

现在我想排除一个特定端点以以这种方式进行身份验证 - 但我不希望它是 [AllowAnonymous]。我想限制对特定 IP 地址的此端点的请求,并为经过身份验证的请求添加自定义声明。我怎样才能实现它?

【问题讨论】:

【参考方案1】:

首先,您需要删除app.UseAuthentication();,因为在您的情况下,这将始终调用默认身份验证方案JwtBearerDefaults.AuthenticationScheme。然后,您可以根据特定的身份验证方案制定特定的授权策略。它可能看起来像这样:

services
    .AddAuthentication()
    .AddScheme<AuthenticationSchemeOptions, Auth1>("Auth1", _ =>  )
    .AddScheme<AuthenticationSchemeOptions, Auth2>("Auth2", _ =>  );

services.AddAuthorization(c =>

    c.AddPolicy("Auth1Policy", policy =>
    
        policy.AuthenticationSchemes.Add("Auth1");
        policy.RequireAuthenticatedUser();
    );

    c.AddPolicy("Auth2Policy", policy =>
    
        policy.AuthenticationSchemes.Add("Auth2");
        policy.RequireAuthenticatedUser();
    );
);

现在使用策略名称注释控制器将仅调用该策略的身份验证方案。以下是您在控制器上选择授权策略的方式:

[HttpGet]
[Authorize(Policy = "Auth1Policy")]
public IEnumerable<WeatherForecast> Get()

但是,如果您将该端点从该服务中取出并将其置于更安全的网络环境中的不同 API 中,那么限制特定 IP 地址将更容易实现,因为公众不应访问它。

【讨论】:

【参考方案2】:

感谢您的建议,但我不想为每个现有控制器添加 [Authorize] 属性。 我只是为 IPAuthentication 添加了新方案:

.AddScheme<IPOnlyAuthenticationOptions, IPOnlyAuthenticationHandler>("IPOnly", op =>  );

然后在AuthenticationHandler中:

public class IPOnlyAuthenticationOptions : AuthenticationSchemeOptions  

public class IPOnlyAuthenticationHandler : AuthenticationHandler<IPOnlyAuthenticationOptions>

    private readonly IEnumerable<IPAddress> validIPs= new[]
    
       "xxx"
    .Select(o => IPAddress.Parse(o));

    public IPOnlyAuthenticationHandler(IOptionsMonitor<IPOnlyAuthenticationOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock)
        : base(options, logger, encoder, clock)  

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    
        var ipAddress = Request.HttpContext.Connection.RemoteIpAddress;
        var identity = GetIdentityFromIPAddress(ipAddress);
        if (identity != null)
        
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), this.Scheme.Name);
            return Task.FromResult(AuthenticateResult.Success(ticket));
        
        return Task.FromResult(AuthenticateResult.Fail($"Request not authenticated for ip address: ipAddress"));
    


    private ClaimsIdentity GetIdentityFromIPAddress(IPAddress ipAddress)
    
        if (smsApiIPs.Contains(ipAddress))
        
            var claims = new[]  new Claim(ClaimTypes.NameIdentifier, "id of my integration user") ;
            return new ClaimsIdentity(claims, nameof(IPOnlyAuthenticationHandler));
        
        return null;
    

我终于可以在我的控制器中使用它了:

    [HttpPost]
    [Authorize(AuthenticationSchemes = "IPOnly")]
    [Route("type/sms/changeStatus")]
    public async Task<IActionResult> Foo(Bar model)

【讨论】:

以上是关于对一个特定端点使用不同的授权,.net 核心的主要内容,如果未能解决你的问题,请参考以下文章

asp .net 核心 wcf 端点

Spring 授权服务器核心协议端点

Angular 4 对 asp.net 核心 API 的请求(在标头中使用授权)不起作用

使用 Keycloak 和 .NET 核心的基于角色的授权

在.net核心应用程序中自托管HTTP(s)端点而不使用asp.net?

ASP.NET 核心,更改未经授权的默认重定向