跨域 - 跨域问题全面理解

什么是跨域问题?

简单来说就是前台调用后端服务接口的时候,如果这个接口不是同一个域的,就会产生跨域问题。由其是前后端分离的项目中很常见。

演示跨域问题

编写后台代码

新建后台工程:

@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/get1")
    public String get1(){
        System.out.println("------------------------------------TestController");
        return "get1 ok----------";
    }
}

编写前台代码

新建前台功能:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-1.4.2.min.js"></script>
</head>
<body>
<a href="#" onclick="get1()">发送get1请求</a>

<script>
    function get1(){
        $.getJSON("http://localhost:8080/test/get1").then(
            function (result) {
                console.log(result);
            }
        );
    }
</script>
</body>
</html>

启动两个工程,访问:http://localhost:8081/# 

上面的报错信息就是跨区问题。

为了后续测试方便,编写测试代码(引入Jasmine测试框架)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" type="text/css" href="jasmine-3.2.0/jasmine.css" />
    <script src="jquery.js"></script>
    <script src="jasmine-3.2.0/jasmine.js"></script>
    <script src="jasmine-3.2.0/jasmine-html.js"></script>
    <script src="jasmine-3.2.0/boot.js"></script>
</head>
<body>
<script>
    //每一个测试用例的超时时间
    jasmine.DEFAULT_TIMEOUT_INTERVAL=1000;
    //请求的接口的前缀
    var base = "http://localhost:8080/test";
    //测试模块
    describe("ajax跨域",function () {
        //测试方法
        it('get1请求', function (done) {
            //服务器的返回结果
            var result;
            $.getJSON(base + "/get1").then(function (jsonObj) {
                result = jsonObj;
            })
            //由于是异步请求,需要使用setTimeout来检验
            setTimeout(function () {
                expect(result).toEqual({
                    "data":"get1 ok"
                })
            })
            //检验完成,通知jasmine框架
            done();
        },100);
    });
</script>
</body>
</html>

访问http://localhost:8081/index.html ,因为跨域返回undefined和预期返回的结果“get1 ok”不一致。

 

为什么会发生AJAX跨域?

1、浏览器限制 (从上面后台打印的结果和浏览器返回结果可以看出,其实结果已经到后来了)

2、跨域(域名、端口一个不一样)

3、发出去的是XHR(XMLHttpRequest)请求(用图片或者script方式就不会有跨域问题)

<script src="http://localhost:8080/test/get1"></script>
<img src="http://localhost:8080/test/get1" alt="" />

 

怎么解决跨域问题(从上面说的3个方面解决)

1、用命令行参数方式启动浏览器禁止检查(从前端的方面去解决)

2、使用JSONP解决跨域,利用script标签请求资源可以跨域来解决跨域问题的。是一种变通的解决方案。非官方协议,是一种约定。

问题:那使用JSONP需要改动后台代码吗?(需要的)

用JSONP的发请求的时候会自动加了一个callback的参数,后台发现callback参数就会知道这是个jsonp请求,就会把返回的JS格式转换成JSON格式(这个后台要写配置代码)。callback生成的值就是需要返回的函数名,而返回的数据就是参数,这就是JSONP实现原理。

除了allback参数还会生成一个参数,这个随机参数是为了防止浏览器缓存的。

JSONP有什么弊端:1、服务器需要改动代码支持(因为如果调用的是别的人就没法改了)2、只支持给方法 3、发送的不是XHR请求(XHR有很多特性:异步等等)

跨域解决方向

1、被调用方解决(基本HTTP协议关于跨域方面的规定,在响应头里面增加指定的字段,告诉浏览器,我允许它调用,这种解决方案是直接从浏览器发送过去的)

2、调用方解决(基于隐藏跨域的思路,这种解决方式请求不会从浏览器直接发送到被调用方,而是从中间的HTTP服务器转发过去的,举个例子假设有调用方a.com和被调用方b.com,第一种解决方案你会在浏览器上面会看到有b.com的url,但第二种看到的都是a.com的url)

猜你喜欢

转载自blog.csdn.net/qq_26857649/article/details/82925902