Русский

Изучите CORS (Cross-Origin Resource Sharing) для безопасной настройки междоменных запросов. Это полное руководство от основ до продвинутых конфигураций для бесшовной и безопасной коммуникации между источниками.

Демистификация CORS: Полное руководство по совместному использованию ресурсов между источниками

В современном взаимосвязанном вебе приложениям часто требуется доступ к ресурсам из разных источников. Именно здесь в игру вступает Cross-Origin Resource Sharing (CORS). CORS — это важнейший механизм безопасности, который определяет, как веб-браузеры обрабатывают запросы от одного источника (домен, протокол и порт) к другому. Понимание CORS необходимо каждому веб-разработчику для создания безопасных и функциональных веб-приложений.

Что такое политика одинакового источника?

Прежде чем углубляться в CORS, важно понять политику одинакового источника (Same-Origin Policy, SOP). SOP — это фундаментальный механизм безопасности, реализованный в веб-браузерах. Его цель — предотвратить доступ вредоносных скриптов с одного веб-сайта к конфиденциальным данным на другом. Источник определяется комбинацией протокола (например, HTTP или HTTPS), домена (например, example.com) и номера порта (например, 80 или 443). Два URL-адреса считаются имеющими один и тот же источник, если у них совпадают протокол, домен и порт.

Пример:

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

Зачем нужен CORS?

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

Рассмотрим сценарий, когда веб-приложению, размещенному на http://example.com, необходимо получить данные с API-сервера, размещенного на http://api.example.net. Без CORS браузер заблокировал бы этот запрос из-за SOP. CORS позволяет API-серверу явно указать, каким источникам разрешен доступ к его ресурсам, обеспечивая правильную работу веб-приложения.

Как работает CORS: Основы

CORS работает через серию HTTP-заголовков, которыми обмениваются клиент (браузер) и сервер. Сервер использует эти заголовки, чтобы сообщить браузеру, разрешено ли ему получать доступ к запрашиваемому ресурсу. Ключевым HTTP-заголовком является Access-Control-Allow-Origin.

Сценарий 1: Простой запрос

«Простой запрос» — это запрос GET, HEAD или POST, который соответствует определенным критериям (например, заголовок Content-Type является одним из application/x-www-form-urlencoded, multipart/form-data или text/plain). В этом случае браузер отправляет запрос непосредственно на сервер, а сервер отвечает с заголовком Access-Control-Allow-Origin.

Запрос клиента (с http://example.com):

GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com

Ответ сервера (с http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json

{
  "data": "Some data from the server"
}

В этом примере сервер отвечает с Access-Control-Allow-Origin: http://example.com, указывая, что запросы с http://example.com разрешены. Если источник в запросе не совпадает со значением в заголовке Access-Control-Allow-Origin (или если заголовок отсутствует), браузер заблокирует ответ и не позволит клиентскому скрипту получить доступ к данным.

Сценарий 2: Предварительный запрос (для сложных запросов)

Для более сложных запросов, таких как те, что используют методы HTTP PUT, DELETE или имеют пользовательские заголовки, браузер выполняет «предварительный» запрос с использованием метода HTTP OPTIONS. Этот предварительный запрос запрашивает у сервера разрешение перед отправкой фактического запроса. Сервер отвечает заголовками, которые указывают, какие методы, заголовки и источники разрешены.

Предварительный запрос клиента (с http://example.com):

OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header

Ответ сервера (с http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600

Объяснение заголовков:

Если ответ сервера на предварительный запрос указывает, что запрос разрешен, браузер переходит к фактическому запросу. В противном случае браузер блокирует запрос.

Фактический запрос клиента (с http://example.com):

PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json

{
  "data": "Some data to be updated"
}

Ответ сервера (с http://api.example.net):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json

{
  "status": "Data updated successfully"
}

Распространенные заголовки CORS

Вот разбивка ключевых заголовков CORS, которые вам нужно понимать:

CORS в различных серверных языках

Реализация CORS обычно включает в себя настройку вашего серверного приложения для отправки соответствующих заголовков CORS. Вот примеры того, как это сделать в различных языках и фреймворках:

Node.js с Express

Вы можете использовать пакет промежуточного ПО cors:

const express = require('express');
const cors = require('cors');

const app = express();

// Включаем CORS для всех источников (ИСПОЛЬЗУЙТЕ С ОСТОРОЖНОСТЬЮ В ПРОДАКШЕНЕ)
app.use(cors());

// Альтернативно, настраиваем CORS для конкретных источников
// app.use(cors({
//   origin: 'http://example.com'
// }));

app.get('/data', (req, res) => {
  res.json({ message: 'This is CORS-enabled for all origins!' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Python с Flask

Вы можете использовать расширение Flask-CORS:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

// Альтернативно, настраиваем CORS для конкретных источников
// CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})

@app.route("/data")
def hello():
    return {"message": "This is CORS-enabled for all origins!"}

if __name__ == '__main__':
    app.run(debug=True)

Java со Spring Boot

Вы можете настроить CORS в вашем приложении Spring Boot с помощью аннотаций или классов конфигурации:

С помощью аннотаций:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@CrossOrigin(origins = "http://example.com") // Разрешить запросы с http://example.com
public class DataController {

    @GetMapping("/data")
    public String getData() {
        return "This is CORS-enabled for http://example.com!";
    }
}

С помощью конфигурации:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/data")
                .allowedOrigins("http://example.com") // Разрешить запросы с http://example.com
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*");
    }
}

PHP

<?php
header("Access-Control-Allow-Origin: http://example.com");
header("Content-Type: application/json");

$data = array("message" => "This is CORS-enabled for http://example.com!");
echo json_encode($data);
?>

CORS и соображения безопасности

Хотя CORS разрешает междоменные запросы, крайне важно реализовывать его безопасно. Вот некоторые важные соображения:

Устранение проблем с CORS

Проблемы с CORS могут быть сложны в отладке. Вот некоторые распространенные проблемы и способы их решения:

Инструменты для отладки:

Продвинутые сценарии CORS

Хотя основные концепции CORS относительно просты, существуют и более продвинутые сценарии, которые следует учитывать:

Лучшие практики CORS

Чтобы обеспечить безопасную и эффективную реализацию CORS, следуйте этим лучшим практикам:

Заключение

CORS — это критически важный механизм безопасности, который обеспечивает контролируемые междоменные запросы в веб-приложениях. Понимание того, как работает CORS и как его правильно настраивать, необходимо каждому веб-разработчику. Следуя рекомендациям и лучшим практикам, изложенным в этом полном руководстве, вы сможете создавать безопасные и функциональные веб-приложения, которые беспрепятственно взаимодействуют с ресурсами из разных источников.

Помните, что всегда нужно отдавать приоритет безопасности и избегать использования слишком разрешительных конфигураций CORS. Тщательно обдумывая последствия для безопасности ваших настроек CORS, вы можете защитить свои приложения и данные от несанкционированного доступа.

Мы надеемся, что это руководство помогло вам демистифицировать CORS. Удачного кодинга!