最近一个项目,因为某些原因,需要从https访问改为http访问,在改造中出现了跨域的问题,在这里记录下。
项目使用nginx做反向代理。
访问网站浏览器会自动跳转到https,需要把nginx http重定向到https给注释了
server {
listen 80;
listen [::]:80;
server_name server_name;
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /usr/share/;
}
location = /.well-known/acme-challenge/ {
return 404;
}
# location / {
# return 301 https://$host$request_uri;
# }
}
这样我们在浏览器访问的时候,就不会自动给我们重定向到了https
在改为http的时候出现了跨域,一般的解决方法就是在nginx加上如下配置
add_header 'Access-Control-Allow-Origin' '*';
但是我们再加上还是出现了以下错误
from origin ‘null’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
这个错误的意思是在预检的时候,浏览器不允许重定向。
我们查看MDN对跨域的定义
跨域实际上是浏览器对不同域访问的一种保护,不然谁都可以随意访问你域名的资源,也是恐怖的
在不是简单的请求的情况下,浏览器一般都会发布一个options预检请求,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
这个设计挺人性化的,总不能直接在你的业务请求上加吧?
回到我们的问题,就是在预检的时候,不允许重定向,可我的地址没有进行重定向,难道什么东西在背后偷偷咪咪的给我做了一层重定向?
请求链路:浏览器–》nginx–》业务
业务是肯定没有重定向的,浏览器也不会无缘无故重定向,那么只有NGINX了
打开浏览器控制台,在网络层我们可以看到
浏览器预检发现状态码是307,那肯定是重定向了,而且一个注意的点,Non-Authoriatative-Reason居然是HTTPS,我们早就把nginx的https换成了http,访问的域名也是http,所以这个地方肯定有问题
add_header Strict-Transport-Security "max-age=63072000" always;
原因在我的nginx配置里有这个配置,大概意思就是 告知浏览器当前域名的所有请求都使用https,这也就是为什么我请求用http,在options探测的时候,自动给我重定向成了https,而cros规定在预检完成前,不允许重定向,所以导致了这里的问题
去掉这句话,或者改成以下形式,重启nginx,清理浏览器缓存,或者改用无痕模式访问,options就不会在重定向了。
add_header Strict-Transport-Security max-age=0;