客户端、服务端,跨域访问设置

同源策略

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。
  1. 协议相同
  2. 域名相同
  3. 端口相同

不同源的网页之间,是无法互相访问cookie、LocalStorage、indexDB的。

大家经常说的跨域访问,CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。http://www.ruanyifeng.com/blog/2016/04/cors.html

跨域访问时,如果客户端发送非简单请求,客户端会首先发送一个option预请求,检查服务端是否支持跨域访问。

客户端

一般客户端指的是常见的浏览器。

1、使用原生XMLHttpRequest方式实现跨域访问:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange=processResponse;
xhr.open("POST", "http://xxx.com/demo/index.php", true);  
xhr.withCredentials = true; //支持跨域发送cookies
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send("id=1");

当跨域访问需要传输被访问域的cookie信息时,设置“xhr.withCredentials = true; ”,此时注意服务端的response header中也要增加header("Access-Control-Allow-Credentials: true"),具体原因稍后说明。

2、使用<script>标签方式实现

var url = "http://xxx.com/demo/index.php?callback=callbackFunction"; 
var script = document.createElement('script');// 创建script标签,设置其属性
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);// 把script标签加入head,此时调用开始

“callbackFunction”为需要回掉执行的函数,返回的是可执行的javscript代码中以调用的方式出现,例如

callbackFunction({"name":"haha"})

使用script标签实现跨域,会同时将目的域的cookie一并传输。

 

3、使用jquery的jsonp请求实现跨域访问:

$.ajax({
    type: "get",
    dataType: "jsonp",
    url: 'http://xxx.com/demo/index.php',
    // jsonp: 'callback', //回调函数参数名
    // jsonpCallback: "callbackFunction",//用户定义的callback函数,没有定义的话会jQuery会自动生成以jQuery开头的函数名
    success: function (json) {
        alert(json);
    }
});

使用jsonp方式实现看跨域,同使用<script>标签的方式一样。

如果指定了jsonpCallback,就不会执行success方法了;没有指定jsonpCallback,会执行success。

注意,服务器返回的数据必须是可执行的javascript,使用指定的callback方法调用

// 如果指定了jsonpCallback为callbackFunction,返回应为是
callbackFunction({"name":"haha"})

// 如果没有指定jsonpCallback,返回结果可能是
jQuery112403687357423576312_1487056485968({"name":"haha"})

 

4、使用jquery的普通ajax请求,实现跨域

$.ajax({
    type: "get",
    url: 'http://localhost/isv',
    xhrFields: { withCredentials: true }, //支持跨域发送cookie
    success: function (json) {
        alert(json);
    }
});

如果需要跨域发送cookie,增加xhrFields: { withCredentials: true },此时注意服务端的response header中也要增加header("Access-Control-Allow-Credentials: true"),具体原因稍后说明。

服务端[1]

需要跨域调用的url,在其返回的response header中,需要增加

httpResponse.addHeader("Access-Control-Allow-Origin", "*");

代表响应所有跨域请求,多个值的话使用"|"分隔。如果response header中没有此设置,浏览器在响应成功后,会阻止回调函数执行,抛出错误。

如果需要跨域访问,request header中有cookie信息,并且

{ withCredentials: true }

服务端的response header中,需要增加

httpResponse.addHeader("Access-Control-Allow-Origin", "http://abc.com");
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");

Access-Control-Allow-Origin不能再使用通配符。

 

tomcat实践

web.xml中增加

<filter>
    <filter-name>CorssFilter</filter-name>
    <filter-class>com.abc.filter.CrossFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>CorssFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

编写指定的filter

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CrossFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        httpResponse.addHeader("Access-Control-Allow-Origin", "*");
        // httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

 

[1]. https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

[2]. http://api.jquery.com/jquery.ajax/

  

posted @ 2017-02-14 16:13  mahuan2  阅读(2425)  评论(0编辑  收藏  举报