Q&A
1. 什么是同源策略?
- 源:协议,域名,端口号。(eg:http://www.baidu.com:80)
- 同源策略:同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,指的是源相同,即协议域名端口号相同。而不同源的客户端脚本未经明确授权的情况下,不能读写对方的资源。
-
** 不是同源策略**:
2. 什么是跨域?跨域有几种实现形式?
- 跨域:从一个页面去请求操作另一个页面的资源,绕过同源策略的限制。
- 需要跨域的情况:
-
跨域的形式:
- 降域:
- 概念:顾名思义,在同一主域名下进行降域,需要用到DOM的domain设置。
- 特点:
- 同域名降域;
- 只对iframe、cookie有效;
- 一旦降域,只能往主域名上降域,不能往前深层更改;
- 安全性受限;
- 试验:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>child1.a.com</title>
</head>
<body style="background:#333">
你好,child1.a.com
<iframe src="//a.com/index.html"></iframe>
<script>
// document.domain = 'a.com'; // 为了验证
window.name = location.href;
var ifr = window.frames[0];
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>a.com</title>
</head>
<body style="background:#fff">
你好,a.com
<script>
document.domain = 'a.com';
window.name = 'index2';
</script>
</body>
</html>
3. jsonp 的原理是什么?
- 原理:
- 动态创建script标签;
- src中传入回调函数的名字;
- 由于JS不同于Ajax,不是同源策略,所以当传入回调函数时,服务器中数据使用callback函数,并且立即生效,达到了类似于跨域的效果。
- 特点:
- 和json并没关系
- 只能进行get请求(因为script只能触发get请求,不能触发post请求)
- 可被注入恶意代码(eg:callback: alert(1);),可用字符串筛选解决;
- 需要校验身份(token):可以共用一套cookie体系实现安全性,也可以使用jsonp自带的token变量进行验证,但是安全性依然有待考量。
- eg:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>child1.a.com</title>
</head>
<body>
<button id="get" type="button">按钮</button>
<div class="show-data"></div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function localHandler(res) {
var str = '';
for(var key in res) {
str += key + ':' + res[key] + '<br>';
}
$('.show-data').html(str);
}
$('#get').on('click', function() {
var url = '//b.com/data.php?callback=localHandler';
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
});
</script>
</body>
</html>
<?php
$res = $_GET['callback'];
$person = array("name"=>"Kevin", "age"=>24, "hobby"=>"painting");
echo $res."(".json_encode($person).")";
?>
4. CORS是什么?
- CORS:CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。
-
兼容性:
- eg:
正常ajax跨域访问的结果:
当添加CORS的响应属性,即Access-Control-Allow-Origin
,浏览器在HTTP响应报文中得到该信息,即可访问源,从而跨域访问数据。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>child1.a.com</title>
</head>
<body>
<button id="get" type="button">按钮</button>
<div class="show-data"></div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function onSuccess(res) {
var str = '';
for(var key in res) {
str += key + ':' + res[key] + '<br>';
}
$('.show-data').html(str);
}
$('#get').on('click', function() {
$.ajax({
url: '//b.com/data.php',
type: 'get',
dataType: 'json',
success: function(res) {
onSuccess(res);
},
error: function() {
alert('异常');
}
});
});
</script>
</body>
</html>
<?php
header('Access-Control-Allow-Origin:*');
$person = array("name"=>"Kevin", "age"=>24, "hobby"=>"painting");
echo json_encode($person);
?>
演示:
1. 本地搭建服务器,演示同源策略
-
本地搭建服务器:
通过修改hosts使用本地IP访问多个域名,得到结果:
child1.a.com下的index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>child1.a.com</title>
</head>
<body>
<button id="get" type="button">按钮</button>
<div class="show-data"></div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function onSuccess(res) {
var str = '';
for(var key in res) {
str += key + ':' + res[key] + '<br>';
}
$('.show-data').html(str);
}
$('#get').on('click', function() {
$.ajax({
url: '//b.com/data.php',
type: 'get',
dataType: 'json',
success: function(res) {
onSuccess(res);
},
error: function() {
alert('异常');
}
});
});
</script>
</body>
</html>
b.com下的data.php:
<?php
// header('Access-Control-Allow-Origin:*');
$person = array("name"=>"Kevin", "age"=>24, "hobby"=>"painting");
echo json_encode($person);
?>
得到结果就是同源策略的限制:
-
CORS:当在data.php中写入
header('Access-Control-Allow-Origin:*')
时,CORS生效,可以访问:
- JSONP:
- 将index.html写成:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>child1.a.com</title>
</head>
<body>
<button id="get" type="button">按钮</button>
<div class="show-data"></div>
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function localHandler(res) {
var str = '';
for(var key in res) {
str += key + ':' + res[key] + '<br>';
}
$('.show-data').html(str);
}
$('#get').on('click', function() {
var url = '//b.com/data.php?callback=localHandler';
var script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
});
</script>
</body>
</html>
- 将data.php改写成:
<?php
$person = array("name"=>"Kevin", "age"=>24, "hobby"=>"painting");
echo $_GET['callback']."(".json_encode($person).")";
?>
由于一级域名不同,不能采用降域的方法。
本文归饥人谷和本人所有,如需转载请注明来源