ajax跨域问题

跨域问题简单的说就是前台请求一个后台链接,发送请求的前台与后台的地址不在同一个域下,就会产生跨域问题。这里所指的域包括协议、IP地址、端口等。

1.跨域访问安全问题

后端代码:

package cn.qs.controller;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

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

    @GetMapping("/get")
    public Map<String, Object> get(@RequestParam Map<String, Object> condition) {
        if (MapUtils.isEmpty(condition)) {
            condition = new LinkedHashMap<>();
            condition.put("param", null);
        }

        return condition;
    }

}

前端代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <script type="text/javascript" src="js/jquery-1.8.3.js" ></script>
    <body>
    </body>
    <script>
        + function test() {
            $.getJSON("http://localhost:8088/test/get.html", {}, function(res) {
                console.log(res);
            });
        }();
        
    </script>
</html>

结果:虽然后端正常响应,但是JS报错,这就是跨域安全问题,如下:

 js报错如下:

  Failed to load http://localhost:8088/test/get.html: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8020' is therefore not allowed access.

发生ajax跨域问题的原因:(三个原因同时满足才可能产生跨域问题)

(1)浏览器限制

  发生ajax跨域的问题的时候后端是正常执行的,从后台打印的日志可以看出,而且后台也会正常返回数据。浏览器为了安全进行了限制,说白了就是浏览器多管闲事。

(2)跨域:

  当协议、域名、端口不一致浏览器就会认为是跨域问题。

(3)XHR(XMLHttpRequest)请求,也就是ajax请求

  如果不是ajax请求,不存在跨域问题(这个我们应该可以理解,浏览器直接访问以及a标签跳转等方式都不会产生跨域问题)。

2.解决思路

 针对上面三个原因可以对跨域问题进行解决。思路如下:

(1)浏览器端:浏览器允许跨域请求,这个不太现实,我们不可能改每个客户端

(2)XHR请求使用JSONP(JSON with Padding)方式进行方式。它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

(3)针对跨域问题解决:

被调用方:也就是服务器端接口,服务器允许跨域。但是如果某些情况服务器端不是我们写的就不可行了。

调用发:也就是JS客户端,隐藏跨域。通常是通过代理的形式隐藏跨域请求,使请求都类似于同一域下发出a标签。

3.浏览器禁止检查-从浏览器层次解决

 比如chrom启动的时候设置参数关闭安全检查,如下:

chrome --disable-web-security --user-data-dir=g:/test

  设置之后可以正常进行访问,这也进一步证明了跨域问题与后台无关。

4..采用JSONP解决,针对XHR原因

  JSONP(JSON with Padding) 是一种变通的方式解决跨域问题。JSONP是一种非官方的协议,双方进行约定一个请求的参数。该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

  JSONP发出的请求类型是script,不是XHR请求,所以可以绕过浏览器的检查。JSONP返回的是application/javascript,普通的xhr请求返回的是application/json。

  JSONP的原理:通过向界面动态的添加script标签来进行发送请求。script标签会加上callback参数以及_,_是为了防止请求被缓存。

    比如我们发送一个请求地址是http://localhost:8088/test/get.html?name=zhangsan&callback=handleCallback&_=123。后端看到有约定的参数callback,就认为是JSONP请求,如果XHR正常请求的响应是{success: true},那么后端会将回传的JSON数据作为参数,callback的值作为方法名,如: handleCallback({success: true}), 并将响应头的Content-Type设为application/javascript,浏览器看到是JS响应,则会执行对应的handleCallback(data)方法。

1.JSONP弊端

(1)服务器端代码需要改动

(2)只支持get方法,由于JSONP原理是通过script标签实现的,所以只能发送get请求

(3)不是XHR异步请求。所以不能使用XHR的一些特性,比如异步等。  

2.测试JSONP  

后端:增加一个advice

package cn.qlq.aspect;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

    public JsonpAdvice() {
        super("callback");
    }
}

前端:采用JSON包装的JSONP请求

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <script type="text/javascript" src="js/jquery-1.8.3.js" ></script>
    <body>
    </body>
    <script>
        + function test() {
                $.ajax({  
                    type : "get",  
                    async:false,  
                    url : "http://localhost:8088/test/get.html?name=zhangsan",  
                    dataType : "jsonp",//数据类型为jsonp  
                    jsonp: "callback",//服务端用于接收callback调用的function名的参数  
                    success : function(data){  
                        console.log(data);
                    },  
                    error:function(){  
                        alert('fail');  
                    }  
                }); 
    
        }();
    </script>
</html>

结果:

(1)请求是script

 请求头:

(2)查看响应数据头和数据:

 数据如下:

/**/jQuery18309128178844464243_1575299406254({"name":"zhangsan","callback":"jQuery18309128178844464243_1575299406254","_":"1575299406287"});

 补充:JSONP也可以自己定义返回的方法名称,默认是JSON生成的随机字符串

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <script type="text/javascript" src="js/jquery-1.8.3.js" ></script>
    <body>
    </body>
    <script>
        var handleJSONPresponse = function (res) {
            console.log(1);
            console.log(res);
            console.log(2);
        }
        function test() {
                $.ajax({  
                    type : "get",  
                    async:fal
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值