【问题标题】:ASP.NET Cors > allow only one originASP.NET Cors > 只允许一个来源
【发布时间】:2021-11-11 08:11:53
【问题描述】:

为此,我们在 StackOverflow 上进行了很多研究,但似乎无法让它发挥作用。

我们的场景如下。我们有服务器 A 和服务器 B。 服务器 A 是一个与服务器 B 通信的 Web API,服务器 B 也是一个 Web API。 服务器 B 应该只处理来自服务器 A 的 http 请求并拒绝所有其他请求。 我们正在尝试通过使用 cors 来强制执行此操作

public void ConfigureServices(IServiceCollection services)
{       
    services.AddCors(options =>
    {
        options.AddPolicy(name: "AllowSpecificOrigin", builder =>
        {
            builder.WithOrigins(new string[0]); // Empty list as a test.
        });
    });

    ...
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
{
    app.UseRouting();

    app.UseCors("AllowSpecificOrigin");

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
    ...
}

但现在在我们的一个控制器中,有两种方法。一种需要 CORS,另一种不需要。

[ApiController]
[Route("api/Server")]
public sealed class ServerController : ControllerBase
{
    [HttpGet]
    [Route("ServerCheck")]
    [DisableCors]
    public IActionResult ServerCheck()
    {
        return Ok(true);
    }

    
    [HttpGet]
    [Route("Version")]
    [EnableCors("AllowSpecificOrigin")]
    public IActionResult Version()
    {
        return Ok(GetType().Assembly.GetName().Version.ToString());
    }
}

如果我知道通过 Postman 向这两种方法发出请求,两种方法都会提供答案。但是既然我们不允许任何来源,那么我们的请求怎么会在控制器中被处理呢?

CORS 是解决此问题的错误方法吗? 最好的方法是什么? 还是我们的配置完全错误?

在我们的 appsettings.json 或 appsettings.Development.json 中没有一行“AllowedHosts”。

【问题讨论】:

  • CORS 用于阻止来自浏览器的请求。来自 Postman 的请求发送不是来自浏览器的请求。您必须创建自定义中间件或过滤器来阻止来源。

标签: asp.net cors


【解决方案1】:

你考虑过IP Address allow list吗?还是 API 密钥或其他形式的身份验证?

似乎您正在尝试利用 CORS 进行访问控制,这不是它的目的。 The Mozilla Docs 相当不错,但简短的版本是 CORS 是一种安全绕过 浏览器 同源限制的方法,您不应该期望它使用 Postman 或任何其他方法以相同的方式工作非浏览器客户端。

同样值得考虑的是,每个标头都可以被攻击者控制,因此不应被信任,任何凭据都应仅通过 https 传输

【讨论】:

  • 谢谢。我似乎忘记了 CORS 确实只是网页安全。
【解决方案2】:

您可以创建一个自定义授权过滤器,通过授权过滤器验证主机是否被允许

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

public class ValidateDomainAttribute : Attribute, IAuthorizationFilter
{
    private IEnumerable<string> AllowedDomains { get; }

    public ValidateDomainAttribute(params string[] domains){
       AllowedDomains = domains;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var host = context.HttpContext.Request.Host;
        if (!AllowedDomains.Contains(host, StringComparer.OrdinalIgnoreCase))
        {
            context.Result = new BadRequestObjectResult("Domain is not allowed !");
        }
    }
}

并通过在 StartUp 类中注册此属性来将其全局应用于所有控制器和操作:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers(options =>
        {
            options.Filters.Add(new ValidateDomainAttribute("your-allowed-domain-1", "your-allowed-domain-2");
        )};
    // rest of code
    }
}

更多关于过滤器属性可以在这里找到:https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-5.0

【讨论】:

猜你喜欢
  • 2021-04-28
  • 2020-12-29
  • 2017-04-27
  • 2013-11-28
  • 2021-05-13
  • 1970-01-01
  • 2019-02-09
  • 2016-06-02
  • 2013-01-29
相关资源
最近更新 更多