• nginx解决跨域问题


     1.1 什么是跨域问题?

    在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制。

    一般根据错误来定位是否是跨域问题,报错如下:

     

    或者:

     

    1.2 常见的跨域场景

     

    URL

    说明

    是否允许通信

    http://www.domain.com/a.js
    http://www.domain.com/b.js
    http://www.domain.com/lab/c.js

    同一域名,不同文件或路径

    允许

    http://www.domain.com:8000/a.js
    http://www.domain.com/b.js

    同一域名,不同端口

    不允许

    http://www.domain.com/a.js
    https://www.domain.com/b.js

    同一域名,不同协议

    不允许

    http://www.domain.com/a.js
    http://192.168.4.12/b.js

    域名和域名对应相同ip

    不允许

    http://www.domain.com/a.js
    http://x.domain.com/b.js
    http://domain.com/c.js

    主域相同,子域不同

    不允许

    http://www.domain1.com/a.js
    http://www.domain2.com/b.js

    不同域名

    不允许

     

     

    1.3 如何解决跨域问题?

    目前我了解的解决跨域的几种方式:手写过滤器,手写拦截器,jsonnp,注解方式,配置nginx反向代理,共五种解决方式。

    我们通常采用修改nginx配置文件来解决跨域问题

    1.3.1 nginx代理跨域

    nginx代理跨域,实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin…等字段。

    1)  nginx配置解决iconfont跨域

    浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。

     

    2)  nginx反向代理接口跨域

    跨域问题:同源策略仅是针对浏览器的安全策略。服务器端调用HTTP接口只是使用HTTP协议,不需要同源策略,也就不存在跨域问题。

    实现思路:通过Nginx配置一个代理服务器域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域访问。

    nginx具体配置:

    server {

          listen   8888;

          server_name test.demo.com;

          location / {

          proxy_pass http://120.147.88.27:8888;

          add_header Access-Control-Allow-Origin *;

          add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

          add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range,Authorization,Accept,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';

          #add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,Accept';

          add_header 'Access-Control-Allow-Headers' '*';

            }

    }


    详细解释:

    add_header Access-Control-Allow-Methods *;

    add_header Access-Control-Allow-Origin $http_origin;

     

    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,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';

    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

    if ($request_method = 'OPTIONS') {

          add_header 'Access-Control-Max-Age' 1728000;

          add_header 'Content-Type' 'text/plain; charset=utf-8';

          add_header 'Content-Length' 0;

          return 204;

        }

     

    1、Access-Control-Allow-Origin,这里使用变量 $http_origin取得当前来源域,大家说用“*”代表允许所有,我实际使用并不成功,原因未知;

    2、Access-Control-Allow-Credentials,为 true 的时候指请求时可带上Cookie,自己按情况配置吧;

    3、Access-Control-Allow-Methods,OPTIONS一定要有的,另外一般也就GET和POST,如果你有其它的也可加进去;

    4、Access-Control-Allow-Headers,这个要注意,里面一定要包含自定义的http头字段(就是说前端请求接口时,如果在http头里加了自定义的字段,这里配置一定要写上相应的字段),从上面可看到我写的比较长,我在网上搜索一些常用的写进去了,里面有“web-token”和“app-token”,这个是我项目里前端请求时设置的,所以我在这里要写上;

    5、Access-Control-Expose-Headers,可不设置,看网上大致意思是默认只能获返回头的6个基本字段,要获取其它额外的,先在这设置才能获取它;

    6、语句“ if ($request_method = 'OPTIONS') { ”,因为浏览器判断是否允许跨域时会先往后端发一个 options 请求,然后根据返回的结果判断是否允许跨域请求,所以这里单独判断这个请求,然后直接返回;

    #   指定允许跨域的方法,*代表所有

    add_header Access-Control-Allow-Methods *;

    #   预检命令的缓存,如果不缓存每次会发送两次请求

    add_header Access-Control-Max-Age 3600;

    #   带cookie请求需要加上这个字段,并设置为true

    add_header Access-Control-Allow-Credentials true;

    #   表示允许这个域跨域调用(客户端发送请求的域名和端口)

    #   $http_origin动态获取请求客户端请求的域   不用*的原因是带cookie的请求不支持*号

    add_header Access-Control-Allow-Origin $http_origin;

    #   表示请求头的字段 动态获取

    add_header Access-Control-Allow-Headers  $http_access_control_request_headers;

    1.4 问题1:配置跨域不生效

    1)使用nginx -V进行查看是否存在header模块,如没有则进行重新编译安装nginx

        --prefix=/app/nginx --with-http_ssl_module --with-stream --add-module=nginx-upload-module-2.2 --add-module=headers-more-nginx-module-master

    2)下载这两个模块编译即可

        headers-more-nginx-module-master.zip

        nginx-upload-module-2.2.zip

     

    1.5 问题2: nginx会去掉带有下划线的Header键值

    原因:nginx对header name的字符做了限制,默认 underscores_in_headers 为off,表示如果    header name中包含下划线,则忽略掉,部署后就获取不到。

    解决:在header里不要用 “_” 下划线,可以用驼峰命名或者其他的符号(如减号-)代替。nginx默认忽略掉下划线可能有些原因。

    在nginx里的 nginx.conf文件中配置http的部分添加 : underscores_in_headers on;(默认值是off)

  • 相关阅读:
    HashMap 原理?jdk1.7 与 1.8区别
    内存泄漏与溢出
    NIO
    Mysql 存储引擎
    编写一个 rpc
    dubbo 与 zookeeper
    MongoDB
    natapp 内网穿透服务
    【AHOI 2009】同类分布
    [HNOI 2016] 序列
  • 原文地址:https://www.cnblogs.com/Leonardo-li/p/13354038.html
Copyright © 2020-2023  润新知