什么是跨域

  • 只要协议、域名、端口有任何一个不同,都被当作是不同的域
    No ‘Access-Control-Allow-Origin’ header is present on
  • CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。
    它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

模拟情景

新建一个html页面放到桌面,单纯的一个按钮ajax访问

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>测试CORS</title>
<link href="css/style.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
    $(function(){
    $("#cors").click(function(){
        $.ajax({
            url:"http://127.0.0.1:8080/index",
            success:function(data){
                alert(data);
            }
        })
    });
});
</script>
</head>
<body>
    <input type="button" id="cors" value="CORS跨域测试" />
</body>
</html>

快速构建一个springboot web工程,新加index controller

@Controller
public class IndexController {
    @RequestMapping("/index")
    @ResponseBody
    public String index() {
         System.out.println("我的sessionId为" + session.getId());
        return "凉凉";
    }
}

上面的页面访问这个控制器。访问桌面页面,提示跨域,因为相当是两个系统互相访问了。

Failed to load http://127.0.0.1:8080/index: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘null’ is therefore not allowed access.

springboot解决方案:

增加cors配置:
新建类CORSConfiguration

@Configuration
public class CORSConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
         registry
                .addMapping("/**")  //匹配访问的路径
                .allowedMethods("*")           //匹配访问的方法
                .allowedOrigins("*")           //匹配允许跨域访问的源 "http://localhost:8081", "http://localhost:8082"
                .allowedHeaders("*");          //匹配允许头部访问
    }
}

主方法同样开启自定义配置注解:@EnableAutoConfiguration
发现可以正常访问了。但是发现后台打印的sessionid每次都变。

我的sessionId为AB1CBA17EABC80F11268082A77BA8B42
我的sessionId为EE66C4D0A525B5DE1CCCC7DA08E39539
我的sessionId为45CB7EC7DCEA715D27801B31A64FEF7A

因为跨域,默认是不支持cookie,所以导致sessionid不能传给服务器。所以每次请求都是新的session。

解决方案:

ajax添加:使用cookies

xhrFields: {
withCredentials: true
}

同时全局配置设置

@Configuration
public class CORSConfiguration implements WebMvcConfigurer {
    @Override
    //全局配置
    public void addCorsMappings(CorsRegistry registry) {
        registry
                .addMapping("/**")  //匹配访问的路径
                .allowedMethods("PUT", "GET" , "POST")           //匹配访问的方法
                .allowedOrigins("*")           //匹配允许跨域访问的源 "http://localhost:8081", "http://localhost:8082"
                .allowedHeaders("*")          //匹配允许头部访问
                .allowCredentials(true);
    }
}

测试访问ajax地址为:http://192.168.1.196:8080/index ,sessionid不变,其他端口不行。传统servlet的设置方式,需要指定对应的地址ip端口

response.addHeader(“Access-Control-Allow-Origin”,
“http://127.0.0.1:8020“);
response.addHeader(“Access-Control-Allow-Credentials”, “true”);

jsoup解决跨域

JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

ajax就改变个类型

$.ajax({
            dataType:'jsonp',
            url:"http://192.168.1.196:8080/index",
            success:function(data){
                alert(data);
            }
        })

服务端:

@Controller
@RequestMapping(value = "", method = RequestMethod.GET)
public class IndexController {

    @RequestMapping(value = "/index")
        public void index(HttpSession session, HttpServletResponse response, HttpServletRequest request) throws IOException {
        System.out.println("我的sessionId为" + session.getId());

        String callBackFuncString = request.getParameter("callback");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();
        //language=JSON
        String json = "\"凉凉\"";
        out.write(callBackFuncString + "(" + json +")");
    }
}

两种方式比较

jsonp是jquery提供的跨域方式
cors是w3c提供的一个跨域标准

jsonp只支持get方式的跨域
cors支持get和post方式的跨域

jsonp支持所有的浏览器(因为所有浏览器都可以使用script标签发送请求)
cors不支持IE10以下的浏览器