跨域分享问题

一、什么是跨域调用问题?

跨域调用是指同一浏览器下,一个页面(属于一个域名)的ajax需要调用另一个域名下的接口等以获取资源,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制

而我们的h5的项目通常都与数据接口部署在不同的域名下面(一般是在不同的二级域名下面),所以浏览器也会限制跨域访问,浏览器对跨域访问不一定是在请求发出的时候,也有可能是在数据response的时候,比如CSRF 跨站攻击原理如下图:


报错如下:


二、常见的解决方案

目前来讲没有不依靠服务器端来跨域请求资源的技术

1、jsonp 需要目标服务器配合一个callback函数。

2、window.name+iframe 需要目标服务器响应window.name

3、window.location.hash+iframe 同样需要目标服务器作处理。

4、html5postMessage+ifrme 这个也是需要目标服务器或者说是目标页面写一个postMessage,主要侧重于前端通讯。

5、CORS  需要服务器设置header Access-Control-Allow-Origin

6、nginx反向代理 这个方法一般很少有人提及,但是他可以不用目标服务器配合,不过需要你搭建一个中转nginx服务器,用于转发请求。

三、解决跨域调用问题

1、Jsonp方式实现(只支持GET请求)

    jsonp方式只支持GET请求方式,有一定的局限性,接口写法如下:
@RequestMapping(value = "/getXXXjsonp", method = RequestMethod.GET)
@ResponseBody
public void getXXXJsonp(HttpServletRequest request,
    			HttpServletResponse response,
    			@RequestParam("callback") String callback) {
    // 业务处理,并得到结果,加入业务处理完需要返回的结果为result
    String json = JSON.toJSONString(result);
    String str = callback + "(" + json + ");";
    try {
        response.getWriter().print(str);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2、CORS方式实现(项目使用该方式实现)

nginx的配置的http设置如下:

http {

  include mime.types;

  server {

    listen    80;

    server_name localhost;

    charset UTF-8;

    location / {

      root html;

      index index.html index.htm;

    }

    # Avoid CORS and reverse proxy settings

    location /h5/ {

      proxy_http_version 1.1;

      proxy_pass http://39.107.235.104/;

      add_header Access-Control-Allow-Origin *;

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

      add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";

      add_header Access-Control-Allow-Credentials true;

    }

  }

}

说明:满足/h5url的请求都会将请求的url进行替换了转发:

http://域名/h5/   替换为:   http://39.107.235.104/

只是需要注意:  /h5/  不能写为 /h5

http://39.107.235.104/  也不能写为   http://39.107.235.104

原理   CORS是一个W3C标准,全称是"跨域资源共享"Cross-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

CORS请求分为简单请求和非简单请求,区别在于是否满足一下条件(简单请求与非简单请求的流程工作流程是不一样的,具体请参见http://www.ruanyifeng.com/blog/2016/04/cors.html):

1)请求方法是以下三种方法之一:HEADGETPOST

2HTTP的头信息不超出以下几种字段:

Accept

Accept-Language

Content-Language

Last-Event-ID

Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

所以一般的接口都是非简单请求,因为接口请求方法可能会使用PUTDELETE请求方式,或者Content-Type字段的类型是application/json

2nginx反向代理

我们使用第六种nginx的反向代理方式进行实现,则需要一台多以的nginx对满足请求的请求进行转发,使用nginxrewrite功能。在nginx.conf中添加一下的location配置:

server {

        listen 8080;

        server_name localhost;

        location / {

            root html;

            index index.html index.htm;

        }

        location ^~/lflyes/h5/ {

            rewrite ^/lflyes/h5/(.*)$ /$1 break;

            proxy_pass http://www.h5.lflyes.com/;

        }

    }

对以上配置进行说明:

1、'^~ /lflyes/h5/ '

  就像上面说的一样是一个匹配规则,用于拦截请求,匹配任何以 /lflyes/h5/开头的地址,匹配符合以后,停止往下搜索正则。

2、rewrite ^/lflyes/h5/(.*)$ /$1 break;

  代表重写拦截进来的请求,并且只能对域名后边的除去传递的参数外的字符串起作用,例如www.c.com/lflyes/h5/api/msg?method=1¶=2重写。只对/lflyes/h5/api/msg重写。

rewrite后面的参数是一个简单的正则 ^/lflyes/h5/(.*)$ ,$1代表正则中的第一个(),$2代表第二个()的值,以此类推。

break代表匹配一个之后停止匹配。

3、proxy_pass

  既是把请求代理到其他主机


猜你喜欢

转载自blog.csdn.net/it_lihongmin/article/details/79608144