Почему совместное использование ресурсов между источниками (CORS) не блокируется на стороне сервера? - PullRequest
0 голосов
/ 09 мая 2020

Я создал 2 проекта: Клиент и Сервер .

Клиент - это веб-приложение Razor, которое содержит javascript в индексе страница для вызова api. Он размещен на http://localhost: 8000 .

Index.cs html

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<div class="container">
    <div class="row">
        <div class="col-6">
            <button id="sender-get">GET</button>

            <div id="content-get"></div>
        </div>
        <div class="col-6">
            <button id="sender-post">POST</button>

            <div id="content-post"></div>
        </div>
    </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.0/js/bootstrap.min.js" integrity="sha256-oKpAiD7qu3bXrWRVxnXLV1h7FlNV+p5YJBIr8LOCFYw=" crossorigin="anonymous"></script>

<script>
    $(document).ready(() => {
        $('#sender-get').click(() => {
            $.get("http://localhost:9000/weatherforecast")
                .done(() => {
                    $('#content-get').text('done');
                })
                .fail(() => {
                    $('#content-get').text('fail');
                });
        });

        $('#sender-post').click(() => {
            $.post("http://localhost:9000/weatherforecast")
                .done(() => {
                    $('#content-post').text('done');
                })
                .fail(() => {
                    $('#content-post').text('fail');
                });
        });
    });
</script>

Server представляет собой веб-API AS PNET Core (3.1) с шаблоном прогноза погоды. Он размещен под http://localhost: 9000 . Он использует промежуточное ПО CORS и настроен для приема запроса с источником http://localhost: 5000 .

WeatherForecastController.cs

namespace Server.Controllers
{
    [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();
        }



        [HttpPost]
        public IEnumerable<WeatherForecast> Post()
        {
            return null;
        }
    }
}

Startup.cs

namespace Server
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddDefaultPolicy(policy =>
                {
                    policy.WithOrigins("http://localhost:5000");
                });
            });

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors();

            app.UseRouting();

            app.UseAuthorization();

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

Когда я нажимаю POST , запрос не выполняется, что является правильным ответом:

enter image description here

Но если вы установите точку останова на контроллере api, он все равно попадет в метод Post ():

enter image description here

1 Ответ

2 голосов
/ 09 мая 2020

Попадание в конечную точку контроллера является ожидаемым.

Ограничения CORS применяются на стороне браузера и никогда не применяются на стороне сервера. Это также верно для упомянутого вами промежуточного программного обеспечения CORS ASP. NET Core. Ответственность промежуточного программного обеспечения заключается исключительно в том, чтобы дать браузеру указание не отправлять запрещенные запросы, если это возможно. Однако некоторые «простые» запросы (например, очень простые GET и POST) всегда будут поступать на сервер - это то, что вы заметили.

CORS сначала может показаться сложным, но как и все в жизни, как только вы заглянете за занавес, все это обретет смысл.

Совместное использование ресурсов между источниками (CORS) - это механизм, который использует дополнительные заголовки HTTP, чтобы сообщить браузерам предоставить веб-приложению работает в одном источнике, доступ к выбранным ресурсам из другого источника. Веб-приложение выполняет HTTP-запрос с несколькими источниками, когда оно запрашивает ресурс, который имеет другое происхождение (домен, протокол или порт) от его собственного.

https://developer.mozilla.org/docs/Web/HTTP/CORS

Для простых запросов (например, большинства HEAD/GET, но также некоторых простых POST, см. https://developer.mozilla.org/docs/Web/HTTP/CORS#Simple_requests для получения подробной информации) браузер просто выполняет запросы и проверяет заголовки CORS в ответ (например, Access-Control-Allow-Origin), чтобы определить, был ли запрос разрешен или результат должен быть отклонен.

Для предварительно настроенных запросов (например, PUT/PATCH/DELETE, но также GET/POST с нестандартными заголовками или содержимым типов, см. https://developer.mozilla.org/docs/Web/HTTP/CORS#Preflighted_requests для подробностей), браузеры выдают так называемый предполетный запрос с HTTP-командой OPTION заранее, чтобы выяснить, разрешает ли конечная точка запросы с перекрестным источником или нет.

Браузер заранее выполняет предполетные запросы для любых запросов, которые могут изменять данные на сервере именно из-за поведения, которое вы наблюдали. Если бы он не использовал безобидный аванс OPTION, сервер просто удалил бы соответствующие запросы, когда он получит запрос DELETE, хотя запрос должен был быть отклонен политиками CORS сервера.

Однако, браузер не выполняет предполетные запросы для простых запросов, таких как большинство GET, поскольку они считаются безопасными. Вот почему ваша точка останова все еще была достигнута, но ответ был отклонен браузером. Это также одна из причин, по которой вы никогда не должны изменять данные в запросах GET, а использовать для этого специальные глаголы, такие как PUT/PATCH/DELETE:)

...