如何防止简单的 CORS GET 请求访问我的 ASP.Net Core API 服务器上的操作方法? [复制]

Posted

技术标签:

【中文标题】如何防止简单的 CORS GET 请求访问我的 ASP.Net Core API 服务器上的操作方法? [复制]【英文标题】:How to prevent simple CORS GET requests from accessing my Action Methods on my ASP.Net Core API Server? [duplicate] 【发布时间】:2021-03-02 15:08:27 【问题描述】:

为了说明我的问题,当您使用 API 端点创建新项目时,我使用了默认的 ASP.Net Core 项目设置。这是我的控制器,带有Get 操作方法:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

    private static readonly string[] Summaries = new[]
    
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    ;

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    
        _logger = logger;
    

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        )
        .ToArray();
    

这是我在Startup 类中的Configure 方法(如您所见,我在开头添加了app.UseCors()):

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

    app.UseCors();

    if (env.IsDevelopment())
    
        app.UseDeveloperExceptionPage();
    

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

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

默认情况下,服务器在https://localhost:44391/ 上运行。 现在我的期望是,使用像这样的默认设置,所有不是来自https://localhost:44391/ 的 CORS 请求都应该被 CORS 策略阻止。为了验证我是否执行了以下步骤:

    我启动了服务器并在我的Get 方法中放置了一个断点 为了模拟跨域 (CORS) 请求,我访问了任意一个随机网站,例如https://***.com/ 打开 Chrome 开发工具并在控制台中运行以下请求我的 get 方法的 javascriptfetch("https://localhost:44391/weatherforecast").then(r=&gt;r.text()).then(console.log); 现在我预计服务器会发送一个 CORS 错误,而我的 Get 方法将永远不会被执行。 实际发生的情况是我的Get 方法中的断点被命中并执行了该方法。之后我才在浏览器控制台中看到了 CORS 错误。

我认为这种行为是错误的,因为如果请求来自另一个来源,我真的很想避免我的 Get 操作方法被完全执行。

所以基本上归结为两个问题:

    为什么 ASP.Net Core CORS 策略以这种方式起作用? 是否有任何方法可以设置 CORS,使所有操作方法都不会执行,除非 CORS 策略允许?还是我需要为此编写一个自定义中间件?

【问题讨论】:

顺便说一句,CORS 是由浏览器执行的,而不是服务器。 【参考方案1】:

"实际发生的是我的 Get 方法中的断点被命中 并执行了该方法。只有在那之后,我才看到 CORS 错误 我的浏览器控制台...我认为这种行为是错误的”

...不,这是预期的行为。 CORS 实际上是由浏览器执行的,基于服务器提供的标头,以及请求是否受 CORS 限制。

服务器无法确定请求是跨域 AJAX 请求还是其他类型的请求(因为 HTTP 请求中的数据不能可靠地提供该信息),因此直接拒绝不在其权力范围内请求。它所能做的就是设置 CORS 标头来告诉客户端如果请求实际上受到 CORS 限制该怎么办。

因此,如果您的请求到达服务器,将始终执行,只有当响应连同标头一起返回给浏览器时,浏览器才决定是否允许请求页面实际看到响应.

直接回答你的两个问题:

    这就是 CORS 通常的工作方式,而不仅仅是 ASP.NET。请参阅上面的说明。 没有。再次,请参阅上面的解释。 (这里唯一的例外是需要飞行前 OPTIONS 请求的请求,其中必须向服务器发出单独的初始 HTTP OPTIONS 请求 - 在这种情况下,除非 OPTIONS 请求指示请求,否则不会命中 Action 方法是允许的。)

此优秀资源中提供了更多详细信息:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

【讨论】:

同样在这种情况下,请求被认为是“简单”请求,因此没有 OPTIONS / 飞行前请求来询问是否可以。 但是在服务器端阻止这些方法的执行不是更有意义吗?在我的脑海中,我认为这会使您的 API 对跨站点请求伪造和跨站点脚本攻击的抵抗力降低,不是吗? “在服务器端阻止这些方法的执行难道不是更有意义吗?”...当然,但正如我在答案中已经提到的,传入的 HTTP 请求的内容不会'没有给服务器足够的信息来可靠地做到这一点。它无法准确说明请求是如何生成的——它无法确定请求是否应该受到 CORS 的限制;只有浏览器才能知道。 "你可以只检查原始 HTTP 标头"...好吧,但问题是它很容易被欺骗,所以任何决心攻击你的服务器的人都会发现很容易绕过。这就是限制由浏览器强制执行的原因,使用 CORS 攻击向量的攻击者无法控制。而且,一个标准的非 AJAX 请求通常不会有该标头 - 因此,如果您基于该标头的存在进行阻止,那么如果它们不符合您的异常规范,您将冒着阻止所有非 AJAX 请求的风险. P.S. nccgroup.com/uk/about-us/newsroom-and-events/blogs/2017/… 很好地解释了为什么 CORS 和 CSRF 并不真正相互关联。 CORS 不会让您或多或少容易受到 CSRF 的攻击。如果您想要 CSRF 保护,无论您的 CORS 策略如何,都需要添加它(因为除此之外,CSRF 攻击可能发生在常规回发中,而不仅仅是 AJAX)。

以上是关于如何防止简单的 CORS GET 请求访问我的 ASP.Net Core API 服务器上的操作方法? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用授权标头发出 GET CORS 请求

发出 POST 请求时如何防止触发 CORS? [复制]

CORS没有成功?我怎样才能防止这种情况?

如何在从 jquery 发送 $.get 请求时启用 CORS?

CORS,防止带有授权标头的请求预检

如何获取 Rails 应用程序的 CORS 标头以访问 aws s3 存储桶?