Nginx обрабатывает различные проблемы и решения, возникающие при пересечении доменов, а также настройку https и небезопасную обработку проблем браузера https.

Каталог статей


предисловие

提示:本人在生产部署服务时遇到一系列跨域问题和https配置问题,特此做以下记录:

Предисловие 1. Что такое междоменный доступ?

Междоменное означает, что страница а хочет получить ресурсы страницы б. Если протоколы, имена доменов, порты и имена поддоменов страниц а и б различаются, или страница а является IP-адресом, а страница б — адресом доменного имени , все действия доступа являются междоменными, а браузеры вообще ограничивают междоменный доступ из соображений безопасности, то есть междоменные запросы ресурсов не разрешены.

Предисловие 2. Каковы условия для междоменной генерации?

注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要。所以,当用java(或者其他语言)调用RESTful api,从来不会报什么跨域错误
вставьте сюда описание изображения


Два часто используемых метода междоменной обработки

1. Как Springboot решает междоменные проблемы?

1.1 Раздельная конфигурация в контроллере

Добавьте междоменные аннотации @CrossOrigin к каждому классу контроллера.

1.2 Глобальная конфигурация в классе @configation

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
    
    
        registry.addMapping("/**")  // 匹配了所有的URL
                .allowedHeaders("*")  // 允许跨域请求包含任意的头信息
                .allowedMethods("*")  // 设置允许的方法
                .allowedOrigins("*")  // 设置允许跨域请求的域名
                .allowCredentials(true);  // 是否允许证书,默认false
    }
}

1.3 Добавьте заголовок ответа в фильтр

protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
    
    
    res.addHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
    res.addHeader("Access-Control-Allow-Methods", "*");
    res.addHeader("Access-Control-Allow-Headers", "Accept,Authorization,DNT,Content-Type,Referer,User-Agent");
    res.addHeader("Access-Control-Allow-Credentials","true"); // 允许携带验证信息
    chain.doFilter(req, res);
}

2. Как nginx решает междоменные проблемы?

2.1 Настройте параметры заголовка ответа для сервера Nginx

Когда возникает междоменная ошибка 403 и на запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin», вам необходимо настроить параметры заголовка ответа для сервера Nginx.

location / {
    
      
    add_header Access-Control-Allow-Origin *; //允许所有请求访问
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; //允许访问的请求类型
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
	//预检请求需要用到
    if ($request_method = 'OPTIONS') {
    
    
        return 204;
    }
}

2.2. Подробная интерпретация каждого параметра

  1. Access-Control-Allow-Origin
服务器默认是不被允许跨域的,给Nginx服务器配置`Access-Control-Allow-Origin *`后,表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。
  1. Access-Control-Allow-Headers предназначен для предотвращения следующих ошибок:
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

Эта ошибка указывает на то, что значение Content-Type текущего запроса не поддерживается. На самом деле это было вызвано тем, что мы инициировали запрос типа «application/json». Здесь задействована концепция: предварительный запрос (предпечатный запрос), см. введение «предпечатного запроса» ниже.

  1. Access-Control-Allow-Methods предназначен для предотвращения следующей ошибки:
    Content-Type не разрешен Access-Control-Allow-Headers в предварительном ответе.

  2. Добавление возврата 204 в OPTIONS предназначено для устранения ошибки, из-за которой Nginx по-прежнему отказывает в доступе при отправке POST-запроса.

发送"预检请求"时,需要用到方法 OPTIONS ,所以服务器需要允许该方法。

Имя домена конфигурации Nginx охватывает несколько доменных имен

Способ 1: используйте встроенные переменные nginx (обычно используются)

server {
    
    
        set $cors '';
        if ($http_origin ~* "^http://deomain01:port$") {
    
    
            set $cors $http_origin;
        }
        if ($http_origin ~* "^http://deomain02:port$") {
    
    
            set $cors $http_origin;
        }
        if ($http_origin ~* "^http://deomain002:port$") {
    
    
            set $cors $http_origin;
        }
        location /live{
    
    
                  ...
                add_header 'Access-Control-Allow-Origin' '$cors';
                add_header 'Access-Control-Allow-Credentials' 'true';
                # 为预检请求加的header
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
                #为预检请求加的header
                add_header 'Access-Control-Allow-Headers' '*';
        }

Объяснение: формат $http_origin предназначен для того, чтобы nginx принимал значение XXX в заголовке запроса.
Здесь берется происхождение, а общий междоменный запрос поставит источник запроса в origin (браузер добавит заголовок origin в заголовок междоменного запроса)
переменная $cors получает нужный междоменный доменное имя и присваивает его «add_header 'Access-Control-Allow-Origin' '$cors'».

Способ 2: использовать карту

  map $http_origin $cors_list{
    
    
		default  http://aaa.cn;
	    "~ http://bbb.cn"  http://bbb.cn;
	}
    server {
    
    
        listen       8089;
        server_name  localhost;
        location /live{
    
    
                  ...
                add_header 'Access-Control-Allow-Origin' '$cors_list';
                add_header 'Access-Control-Allow-Credentials' 'true';
                # 为预检请求加的header
                add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
                #为预检请求加的header
                add_header 'Access-Control-Allow-Headers' '*';
        }

Объяснение:
команда map предоставляется модулем ngx_http_map_module, который по умолчанию загружается nginx.

语法: map $var1 $var2 {
    
    }
默认值: -
配置段: http

map为一个变量设置的映射表。映射表由两列组成,匹配模式和对应的值。

在map块里的参数指定了源变量值和结果值的对应关系。

default: 没有匹配结果将使用的默认值。如果没有设置default,将会用一个空的字符串作为默认的结果。

匹配模式可以是一个简单的字符串或者正则表达式,使用正则表达式要用(‘~’)

Способ 3: Регулярное сопоставление доменных имен третьего уровня

   location / {
    
    

             if ($http_origin ~* (http?://.*\.aliuncle\.top$)) {
    
    
                    add_header Access-Control-Allow-Origin $http_origin;
            }
            index index.php;
            try_files $uri $uri/ /index.php?$args;
    }

Примечание. При настройке кросс-доменности в конфигурационном файле nginx.conf не забудьте очистить клиент, например кэш браузера, иначе конфигурация не вступит в силу.

2.3, nginx обрабатывает различные отчеты об ошибках, возникающих в междоменном процессе.

1. Междоменный запрос не может содержать ошибку файла cookie для учетных данных ()

вставьте сюда описание изображения

Описание проблемы: файл cookie для учетных данных идентификации не может быть передан в запросе в любом случае.

Решение:
внешний интерфейс:
1. Установите для атрибута withCredentials объекта запроса значение true, когда внешний интерфейс запрашивает;
вставьте сюда описание изображения

2. Бэкенд поддерживает заголовок ответа Credentials как true
вставьте сюда описание изображения
注意:除了 Access-Control-Allow-Credentials 之外,跨域发送 Cookie 还要求 Access-Control-Allow-Origin 不允许使用通配符。 事实上不仅不允许通配符,而且 只能指定单一域名:
, иначе будет сообщено об ошибке cros
вставьте сюда описание изображения

2.4, ошибка предполетного запроса (предполетный запрос)

вставьте сюда описание изображения

Введение.
Стандарт Cross-Origin Resource Sharing (CORS) добавляет новый набор полей заголовка HTTP, позволяя серверу объявлять, какие исходные сайты имеют разрешение на доступ к тем или иным ресурсам. Кроме того, спецификация требует, чтобы для тех методов HTTP-запросов, которые могут оказывать побочные эффекты на данные сервера (особенно HTTP-запросы, отличные от GET, или POST-запросы с определенными типами MIME ), браузер должен сначала использовать метод OPTIONS для инициации предварительного запроса. (предварительный запрос), чтобы узнать, разрешает ли сервер междоменный запрос. После того, как сервер подтвердит разрешение, инициируется фактический HTTP-запрос. При возврате запроса предварительной проверки сервер также может уведомить клиента о том, следует ли передавать идентификационные данные (включая файлы cookie и данные, связанные с аутентификацией HTTP).
На самом деле запрос, поле Content-Type которого равно application/json, является вышеупомянутым POST-запросом с определенными типами MIME.CORS предусматривает, что все Content-Type, не принадлежащие к следующим типам MIME, являются предварительными запросами:

application/x-www-form-urlencoded
multipart/form-data
text/plain

2.4.1. Ожидаемый процесс запроса (сначала отправьте запрос/ответ параметров, затем отправьте почтовый запрос)

вставьте сюда описание изображения

2.4.2, ошибка запроса предварительной проверки

Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.

Объяснение:
запрос application/json добавит запрос «предварительной проверки» перед официальным сообщением. Этот запрос «предварительной проверки» принесет информацию заголовка. Когда сервер ответит, если возвращенная информация заголовка не содержит Access-Control - Allow-Headers: Content-Type указывает, что Content-Type не по умолчанию не принимается. То есть возникает вышеуказанная ошибка:

预检请求头信息
Access-Control-Request-Headers: Content-Type:
OPTIONS /api/test HTTP/1.1
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

2.4.3 Как решить сообщение об ошибке запроса на предварительную проверку?

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

//预检请求需要用到
    if ($request_method = 'OPTIONS') {
    
    
        return 204;
    }

Подробное объяснение кода состояния nginx

Подробное объяснение http

2.4.4 Access-Control-Allow-Origin можно установить только один раз, после настройки в бэкенде его нельзя настроить повторно в nginx

Сообщается о следующей ошибке:
вставьте сюда описание изображения
Объяснение: Значение Access-Control-Allow-Origin, возвращаемое сервером, не должно быть списком, поскольку браузер примет только одно значение, и оно не может быть пустым.

2.5 Заголовок запроса содержит дополнительную информацию, такую ​​как авторизация.

вставьте сюда описание изображения

报错:(Авторизация поля заголовка запроса не разрешена Access-Control-Allow-Headers в предварительной проверке)

2.5.1, Пояснение

Заголовок ответа Access-Control-Allow-Headers используется в предварительном запросе (preflight request) и содержит информацию заголовка, которая появится в поле Access-Control-Request-Headers формального запроса. Простые заголовки, такие как простые заголовки Accept, Accept-Language, Content-Language, Content-Type (ограничены тремя значениями MIME: application/x-www-form-urlencoded, multipart/form-data или text/plain после разбора типа (исключая параметры)), они всегда поддерживаются и не нуждаются в специальном указании в этом заголовке.

Должна быть разрешена дополнительная информация в заголовке запроса, такая как авторизация и токен X. Об этой ошибке сообщается посредством предварительной обработки запроса, чтобы узнать, что авторизация в заголовке запроса не разрешена, поэтому он сообщает о междоменном

2.5.2 Решить

Необходимо добавить разрешенный заголовок Authorization, и, когда будет определено, что метод запроса имеет параметры, вернуть клиенту ok (200), чтобы можно было продолжить формальный почтовый запрос.

    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PATCH, DELETE, PUT, OPTIONS';
	add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, X-Custom-Header, Access-Control-Expose-Headers, Token, Authorization';
	add_header 'Access-Control-Allow-Headers'  '*';
    add_header 'Access-Control-Max-Age' 1728000;

2.6 Углубленный анализ и устранение междоменных ошибок в новой версии Google: запрос клиента не является безопасным контекстом, а ресурс находится в более приватном адресе

2.6.1 Причины сообщения об ошибке

Ошибка: небезопасный запросчик запросил более закрытый локальный ресурс
вставьте сюда описание изображения

Причина: Начиная с версии Google 94, Google обновил частную сеть для небезопасных веб-сайтов, чтобы блокировать такие запросы на доступ к большему количеству частных ресурсов. При этом перед запросом ресурсов частной сети сначала будет отправлен предварительный запрос OPTIONS.

2.6.2 Решения

1. Замените браузеры без ядра Google (используя Firefox, edge и т.д.) или понизьте версию

2. Измените настройки Google Chrome Решение
: отключите настройки Для версий Google Chrome между 94 и 101 вы можете изменить настройки браузера, чтобы запросы на личные ресурсы, отправленные веб-сайтами http, могли быть успешно отправлены.

Действуйте следующим образом:

Шаг 1. Введите в браузере: chrome://flags/#block-insecure-private-network-requests.

Шаг 2: Измените значение по умолчанию для параметра Блокировать незащищенные частные сетевые запросы на Отключено и перезапустите браузер (разные версии имеют разные конфигурации, подробности см. по следующей справочной ссылке). См. ссылку 3. Измените метод доступа изображения интрасети и другие ресурсы
вставьте сюда описание изображения
,
все Использование https-доступа может в корне решить проблему

Как настроить https (настроить ssl в nginx)

1. Конфигурация

Обобщите следующие шаги: подайте заявку на ssl->хранилище файлов ssl на сервер->nginx, настройте ssl

  server {
    
    
                listen       8002 ssl;          
                server_name temp.3zyun.com ;   #公网ip      115.148.208.122                                       
                client_max_body_size 1024M;
                ssl_certificate /usr/local/nginx/yjssl/7604469_temp.3zyun.com_nginx/7604469_temp.3zyun.com.pem;
        ssl_certificate_key /usr/local/nginx/yjssl/7604469_temp.3zyun.com_nginx/7604469_temp.3zyun.com.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on ;
                location / {
    
    
                         
                        proxy_pass http://bpm-server/;
                        proxy_set_header Host $host:$server_port;
                }
        }

注意 :端口后面要加上ssl才可生效
Конфигурация ssl была вдохновлена ​​этой статьей

2. Ряд возникших проблем

2.1. Проект h5 упакован и развернут в рабочей среде.

Смешанное содержимое: страница 'xxx' была загружена через HTTPS, но запросила небезопасный ресурс 'xxx'. Этот запрос был заблокирован, контент должен передаваться через HTTPS Объяснение решения проблемы: когда наш браузер выглядит как "был загружен
вставьте сюда описание изображения
через Ошибка HTTPS, но запрошен небезопасный ресурс/фрейм», как правило, потому, что наш веб-сайт использует HTTPS, а ссылка другой стороны — протокол HTTP, поэтому при запросах Ajax или javascript он сообщит об указанной выше ошибке при запросе интерфейса http или импорте ресурсов http. в https будет напрямую заблокировано (заблокировано), браузер по умолчанию считает такое поведение небезопасным и заблокирует его.

Решение:

(在index.html的head中加入以下代码)
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />

Функция: принцип добавления этого тега заключается в использовании тега META для принудительного преобразования запросов http в запросы https (протокол SSL).

Подведем итог

Всегда расти после того, как постоянно наступил на яму! ! !

рекомендация

отblog.csdn.net/wei1359765074410/article/details/127510086