Fork me on GitHub

跨域请求

跨域问题是由于浏览器为了防止CSRF攻击, 避免恶意攻击而带来的风险而采取的同源策略限制. 当一个页面中使用XMLHTTPRequest对象发送HTTP请求时(XHR请求), 必须保证当前页面和请求的对象是同源的, 即协议域名端口号要完全一致, 否则浏览器就会阻止此跨域请求返回的数据.

http://www.a.comhttps://www.a.com 是不同源的, 它们协议不同
http://www.a.comhttp://www.b.com 是不同源的, 它们域名不同
http://www.a.com:80http://www.a.com:8080 是不同源的,它们端口号不同
http://www.a.com/test1.jshttp://www.a.com/test2.js 是同源的

同源策略 Same-Origin-Policy(SOP)

浏览器采用同源策略, 禁止页面加载或执行与自身来源不同的域的任何脚本. 换句话说浏览器禁止的是来自不同源的”document”或脚本. 对当前”document”读取或设置某些属性.
情景:
比如一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。
浏览器中有哪些不受同源限制呢?
<script><img><iframe><link>这些包含 src属性的标签可以加载跨域资源

jsonp跨域

知道了某些标签可以加载跨域资源, 我们可以通过伪造这些标签来加载跨域资源

html
1
<script src="../static/js/test.js"></script>

test.js
1
alert("jaonp测试");

访问页面将会弹出一个提示窗体,显示jsonp测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<p>hello</p>
<button class="get_service">jsonp测试</button>

<script src="../static/js/test.js"></script>
<script>
$(".get_service").click(function () {
$.ajax({
url: "http://127.0.0.1:8080/jsonp/func/",
success: function (data) {
alert(data);
}
})
})
</script>

开两个服务器, 一个跑在8888端口, 一个跑在8080端口
访问8888端口, 点击按钮, 并没有窗体提示, 控制台报了同源策略的错

1
已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8080/jsonp/func/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

使用src来进行改进, 当点击按钮时生成script标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 function test(arg) {
console.log(arg);
}

function get_jsonp_data(url) {
var ele_script=$("<script>");
ele_script.attr("src",url)
ele_script.attr("id","jsonp");
$("body").append(ele_script);
$("#jsonp").remove()
}
$(".get_service-2").click(function () {
get_jsonp_data("http://127.0.0.1:8080/jsonp/func/?callback=test")
});

服务端
1
2
3
4
5
6
7
def func(request):
cb = request.GET.get('callback')
info = {
'name': 'jsonp测试',
'num': '111111222'
}
return HttpResponse("{}({})".format(cb,json.dumps(info)))

这样点击按钮时就会在控制台打印数据,
但是这样的坏处在于函数写死了, callback后面跟的什么, js中就要有相应的函数

使用ajax来进行跨域请求

1
2
3
4
5
6
7
8
9
10
11
12
$(".get_service-3").click(function () {
$.ajax({
url: "http://127.0.0.1:8080/jsonp/func/",
type: "get",
dataType: "jsonp", // 伪造ajax 基于script
jsonp: 'callback',
jsonpCallback:"test",
success: function (res) {
console.log(res);
}
})
})

这样在点击按钮的时候也能加载数据, 控制台也打印了数据
其中的jsonpCallbacksuccess保留一个即可, 都保留的话都会执行

不加'jsonpCallback'会生成一个随机函数名
1
2
"GET /jsonp/func/?callback=jQuery34109073627782543463_1558861601824&_=1558861601827 HTTP/1.1" 200 91
"GET /jsonp/func/?callback=test&_=1558861614750 HTTP/1.1" 200 55

jsonp只能发get请求

一个公开的接口

1
2
3
4
5
6
7
8
9
10
11
12
$(".get_service-4").click(function () {
$.ajax({
url: "http://www.jxntv.cn/data/jmd-jxtv2.html",
type: "get",
dataType: "jsonp", // 伪造ajax 基于script
jsonp: 'callback',
jsonpCallback:"list",
success: function (res) {
console.log(res);
}
})
})

jsonpCallback必须是list, 服务器返回的是list

cors

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

常用方法, 设置Access-Control-Allow-Origin

1
2
3
response=HttpResponse()
response["Access-Control-Allow-Origin"]="*"
return response

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!
0%