二十一:Ajax跨域请求带来的同源策略问题,及其解决

一、同源

1、先来说说什么是源
• 源(origin)就是协议、域名和端口号。
以上url中的源就是:http://www.company.com:80
若地址里面的协议、域名和端口号均相同则属于同源。
以下是相对于 http://www.a.com/test/index.html 的同源检测
http://www.a.com/dir/page.html —-成功
http://www.child.a.com/test/index.html —-失败,域名不同
https://www.a.com/test/index.html —-失败,协议不同
http://www.a.com:8080/test/index.html —-失败,端口号不同

2.什么是同源策略?
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。

• 不受同源策略限制的:
1、页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
2、跨域资源的引入是可以的。但是js不能读写加载的内容。如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等。

二、跨域
1、什么是跨域
受前面所讲的浏览器同源策略的影响,不是同源的脚本不能操作其他源下面的对象。想要操作另一个源下的对象是就需要跨域。

2、何时需要跨域
就如前面所说,当想要操作另一个源下的对象是就需要跨域。

三、如何实现跨域请求
(一)简单易用JsonP

1、前端ajax请求

function search(){
    $.ajax({
        type: "get",
        url: url_pre + "/book",
        async:true,
        //这里不同于普通ajax请求(1)
        dataType:"JSONP",
        //这里不同于普通ajax请求(2)
        jsonp:"callback",
        //这里不同于普通ajax请求(3),不加这个,jQuery就会随机生成一个
        jsonpCallback:"success_jsonpCallback",
        data : {
            "key" : $('#key').val(),
            "tag" : $('#tag').val(),
            "doubanScore" : $('#doubanScore').val(),
            "sort" : $('#sort').val()
        },
        success : function(response){
            if(response.code === 1){
                for(var i=0; i<response.data.length; i++){
                    console.info("id: "+ response.data[i].id + " name: " + response.data[i].name + " author:" + response.data[i].author);
                }
            }
        }
    });
}

2、后端
普通的json数据

{
    "message":"获取成功",
    "state":"1",
    "result":{"name":"工作组1","id":1,"description":"11"}
}

jsonp格式数据

callback({
    "message":"获取成功",
    "state":"1",
    "result":{"name":"工作组1","id":1,"description":"11"}
})

  所以像以前一样只加个@ResponseBody注解得到的数据,前端是无法解析的。后台需要做相应的配合工作:

package org.pc.advice;

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

/**
 * @author 咸鱼
 * @date 2018/8/24 17:16
 */
@ControllerAdvice(basePackages = "org.pc")
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
    public JsonpAdvice(){
        super("callback", "jsonp");
    }
}

  这样就会对所有返回的json格式数据进行包装,包装为jsonp格式的数据,前台可以正常解析。

3、JsonP优缺点

  • 无法发送POST请求,也就是说JSONP技术只能用于请求异域资源,无法上传数据或修改异域数据;
  • 无法监测JSONP请求是否失败;
  • 可能存在安全隐患:别忘了,JSONP之所以能成功获取异域服务器资源,靠的是服务器动态生成了回调函数,并在页面中执行,那么如果服务器在原有的回调函数下再添加些别的恶意JavaScript代码会怎样?当然也会被执行!所以在使用JSONP技术时,一定要确保请求资源的服务器是值得信赖的;

参见ResponseBody返回JsonP格式

猜你喜欢

转载自blog.csdn.net/panchang199266/article/details/82022319