一、背景说明
项目中Https强转逻辑是在nginx层面配置的,Cross跨域逻辑处理是在项目的Java代码层面处理的。
向服务器发起Http跨域请求时,出现Cross跨域逻辑处理失效问题
nginx 中Https 强转配置,如下所示:
if ($server_port = 80 ) {
rewrite ^(.*)$ https://$host$1 permanent;
}
Cross跨域逻辑处理层,代码如下所示:
String originUrl = request.getHeader("origin");//请求的地址
if (StringUtils.isNotEmpty(originUrl)){
if (originUrl.endsWith("test.com")){
response.setHeader("Access-Control-Allow-Origin", originUrl);
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.setHeader("Access-Control-Max-Age", "1800");//30分钟
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,frLo");
}
if (request.getMethod().equalsIgnoreCase(HttpMethod.OPTIONS.name())) {
response.setStatus(200);
return false;
}
}
二、问题描述
1)例如:在sun.test.com系统中,使用JS脚本发起Ajax请求,向my.timer.com服务器发起Http请求,my.timer.com服务器中配置了以上的Https强转和Cross逻辑处理代码。
2)my.timer.com 服务器的nginx收到Http请求后,会执行Https强转,然后发起重定向rewrite Https请求,此时由于发起了重定向请求导致原跨域请求header中的origin 参数丢失
注:rewrite 和 return 301 https://$host$request_uri; 都会导致header 中的orgin参数丢失,因为两种方式都是发起重定向请求
3) my.timer.com 服务器再次收到第2步重定向后的Https请求,由于header中的origin参数丢失,最终导致后端java Cross跨域处理逻辑失效,由于Cross 是否跨域请求都是借助header中的origin参数来处理的
三、问题尝试解决
1)考虑在nginx中 rewrite之前 使用 add_header 'Origin' $http_origin; 添加header,无法解决问题,因为rewrite 是重定向请求,add_header 无法生效
2)将Cross 跨域逻辑处理转移到nginx中配置如下所示:
set $cors "false";
if ($http_origin ~* "(test.com)") {
set $cors "true0";
}
if ($request_method = 'OPTIONS') {
set $cors "true1";
}
if ($cors = "true0") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
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';
add_header 'Access-Control-Max-Age' 1728000;
}
if ($cors = "true1") {
add_header 'Access-Control-Allow-Origin' "$http_origin";
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Origin,X-Requested-With,Content-Type,Accept,frLo';
add_header 'Access-Control-Max-Age' 1728000;
return 200;
}
if ($server_port = 80 ) {
rewrite ^(.*)$ https://$host$1 permanent;
}
还是无法解决以上问题
四、解决方案
未找到完美解决方案,只能让sun.test.com系统中发起跨域Ajax请求时,默认使用Https协议请求服务器,避开服务的Http请求强转。