Оригинальный адрес:xeblog.cn/articles/12
введение
Несмотря на то, что интерфейсные и внутренние проекты разделены, степень связи снижается, но также возникают различные проблемы. Внутренний проект развертывается Tomcat (прослушивание порта 8080), а внешний проект развертывается на Nginx (прослушивание портов, отличных от 8080, таких как 80, 443), скорость загрузки внешней страницы значительно повышается. , но сообщается об ошибке, когда ajax запрашивает внутренний интерфейс.
Та же политика происхождения
Политика того же происхождения — хорошо известная политика безопасности, предложенная Netscape. Все браузеры, поддерживающие JavaScript, теперь используют эту стратегию. Так называемый гомологичный означает, что доменное имя, протокол и порт совпадают.
Внешний адрес:http://127.0.0.1:63344
Адрес бэкенда:http://127.0.0.1:8080
Хотя IP-адреса и протоколы этих двух адресов одинаковы, порты разные, поэтому они не соответствуют одному и тому же происхождению, что вызывает междоменные проблемы.
решение
Настройка addCorsMappings
Добавьте реализацию классаWebMvcConfigurer
Интерфейс, а затем добавить этот класс@Configuration
Примечания, наконец, понялиaddCorsMappings
метод в порядке.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
.maxAge(3600)
.allowCredentials(true);
}
}
нормальный запрос
Это конец? Это так просто?
Войдите в фоновое управление
wtf?
Почему запрос OPTIONS?
按照我的逻辑,上面那个报错的接口应该是一个GET请求,可为什么发的是OPTIONS请求?翻阅各种资料,各种百度google,各种倒腾,各种头疼,最后。 . .我掀开了被子,惊奇的发现。 . .被窝可真暖和啊! (先睡一觉再说)
причина
Получается, что браузер перед отправкой реального запроса отправит предварительный запрос с методом OPTIONS.Preflighted requests
Этот запрос используется для проверки того, является ли запрос безопасным, и не все запросы будут отправлены при соблюдении следующих условий:
- Метод запроса не GET/HEAD/POST
- Content-Type запроса POST не является application/x-www-form-urlencoded, multipart/form-data или text/plain.
- В запросе установлено настраиваемое поле заголовка
Для интерфейса со стороны управления я должен проверить разрешения интерфейса, и каждый запрос должен содержать настраиваемое поле (токен) в заголовке, поэтому браузер отправит еще один запрос OPTIONS.
Почему OPTIONS запрашивают ошибку. . .
После отладки было обнаружено, что запрос OPTIONS несет только настраиваемые поля и не вносит соответствующие значения. Когда поле токена проверяется в фоновом режиме, токенNULL
, поэтому проверка завершается неудачно и выдается исключение.
ВАРИАНТЫ выпуска
Я переключился на междоменное решение, используя перехватчик для решения междоменной проблемы и отпустив запрос OPTIONS.
Добавьте класс перехватчикаCorsInterceptor
выполнитьHandlerInterceptor
интерфейс
@Component
public class CorsInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "86400");
response.setHeader("Access-Control-Allow-Headers", "*");
// 如果是OPTIONS则结束请求
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return false;
}
return true;
}
}
Нужно проверить на перехватчик перехватчика перехвата пересекания пересекания выше
Ставлю оригинальную междоменную конфигурациюaddCorsMappings
удален
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
@Resource
private CorsInterceptor corsInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 跨域拦截器需放在最上面
registry.addInterceptor(corsInterceptor).addPathPatterns("/**");
// 校验token的拦截器
registry.addInterceptor(loginInterceptor).addPathPatterns("/admin/**");
}
}
запрос OPTIONS в порядке
GET-запросы также отправляются последовательно
Суммировать
Спокойной ночи!
Добавка
Access-Control-Allow-Credentials
响应头表示是否可以将对请求的响应暴露给页面。 возвращениеtrue
тогда да, никаких других значений. Полномочия могут бытьcookies, authorization headers
илиTLS client certificates
. Если установлено значение true, сервер НЕ ДОЛЖЕН устанавливатьAccess-Control-Allow-Origin
значение*
, нужно указать доменное имя, иначе при необходимости отправитьCookie
Когда браузер отвечает, браузер отвечает.
контрольная работа
Ajax-запрос включенwithCredentials
Атрибуты
xhrFields: {
withCredentials: true
}
Когда внутренняя междоменная конфигурация остается неизменной, результат запроса браузера сообщает об ошибке.
уточнитьAccess-Control-Allow-Origin
значениеhttp://127.0.0.1:63344
, Нормальный запрос снова
Окончательная конфигурация
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 此处配置的是允许任意域名跨域请求,可根据需求指定
response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "86400");
response.setHeader("Access-Control-Allow-Headers", "*");
// 如果是OPTIONS则结束请求
if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
response.setStatus(HttpStatus.NO_CONTENT.value());
return false;
}
return true;
}