一、 什么是同源策略
同源策略是由Netscape提出的安全策略,所有支持JavaScript的浏览器都会使用这个策略。即浏览器出于安全方面的考虑,只允许与本域名下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。所谓同源是指 协议、域名、端口相同。
二、 什么是跨域?跨域有几种实现形式
跨域是指从一个域名的网页去请求另一个域名的资源。比如从http://google.com 面去访问 http://jirengu.com 的资源,跨域严格来说只要协议,端口,域名有任何一个不同的,就是跨域。
跨域访问有四种实现形式:
1、JSONP 由于script标签不受同源策略限制,可动态创建script,先创建一个script标签,可以加载任何内容,把请求页面当成js文件解析,之后再删除。
2、CORS (Cross-Origin Resource Sharing)是一种ajax跨域请求资源的方式,进行跨域请求时,请求头加一个origin,后台响应头加Access-Control-Allow-Origin
3、使用降域实现跨域(在拥有的相同的父域名时才可实现),现有的域名写成相同的父域名,请求访问的域名写成相同的父域名。
4、postMessage window下的一个跨域方法
三、 JSONP 的原理是什么
由于浏览器的同源策略时,不能向不同的域提交请求。JSONP(JSON with Padding)实现跨域原理是:
首先在注册一个callback, 然后把callback的名字传给后台。此时,服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp。最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里。
由于使用script标签的src属性,因此只支持get方法
一个简单的jsonp实现,其实就是拼接url,然后将动态添加一个script元素到头部
四、CORS是什么
CORS跨域资源共享(Cross-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。需要浏览器和服务器同时支持。整个过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
即使用XMLHttpRequest跨域请求时,浏览器会再请求头中添加:Origin,后端如果认为可以接受请求会在Access-Control-Allow-Origin 相应添加一个包含Origin的值。
五、 根据视频里的讲解演示三种以上跨域的解决方式
(一)用jsonp实现降域
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
ol{
list-style: none;
}
.content li{
padding: 10px;
border:1px solid #000;
margin: 10px;
border-radius: 4px;
}
#btn{
padding:10px;
background-color:#eee;
border-radius:4px;
margin:10px;
}
</style>
</head>
<body>
<ol class="content">
<li>侯佩岑怀二胎孕照 </li>
<li>上海现史诗级骂街 </li>
<li>侯佩岑怀二胎孕照 </li>
</ol>
<button id="btn">获取更多</button>
</div>
<script type="text/javascript">
$('#btn').addEventListener('click',function(){
var script=document.createElement('script')
script.src="http://b.jrg.com:8080/getNews?callback= appendHtml";
document.head.appendChild(script);
document.head.removeChild(script);
})
function appendHtml(news){
console.log(news)
var html='';
for (var i = 0; i < news.length; i++) {
if(!news[i]){continue}
html+='<li>'+news[i]+'</li>';
}
console.log(html);
$('.content').innerHTML = html;
}
function $(id){
return document.querySelector(id);
}
</script>
</body>
</html>
router.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
ol{
list-style: none;
}
.content li{
padding: 10px;
border:1px solid #000;
margin: 10px;
border-radius: 4px;
}
#btn{
padding:10px;
background-color:#eee;
border-radius:4px;
margin:10px;
}
</style>
</head>
<body>
<ol class="content">
<li>侯佩岑怀二胎孕照 </li>
<li>上海现史诗级骂街 </li>
<li>侯佩岑怀二胎孕照 </li>
</ol>
<button id="btn">获取更多</button>
</div>
<script type="text/javascript">
$('#btn').addEventListener('click',function(){
var script=document.createElement('script')
script.src="http://b.jrg.com:8080/getNews?callback= appendHtml";
document.head.appendChild(script);
document.head.removeChild(script);
})
function appendHtml(news){
console.log(news)
var html='';
for (var i = 0; i < news.length; i++) {
if(!news[i]){continue}
html+='<li>'+news[i]+'</li>';
}
console.log(html);
$('.content').innerHTML = html;
}
function $(id){
return document.querySelector(id);
}
</script>
</body>
</html>
实现效果
(二)cors实现降域
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
ol{
list-style: none;
}
.content li{
padding: 10px;
border:1px solid #000;
margin: 10px;
border-radius: 4px;
}
#btn{
padding:10px;
background-color:#eee;
border-radius:4px;
margin:10px;
}
</style>
</head>
<body>
<ol class="content">
<li>侯佩岑怀二胎孕照 </li>
<li>上海现史诗级骂街 </li>
</ol>
<button id="btn">换一组</button>
</div>
<script type="text/javascript">
$('#btn').addEventListener('click',function(){
var xhr=new XMLHttpRequest();
xhr.open('get','http://a.jrg.com:8080/getNews',true);
xhr.send();
xhr.onreadystatechange=function(){
if (xhr.readyState === 4 && xhr.status===200){
appendHtml(JSON.parse(xhr.responseText))
}
}
})
function appendHtml(news){
console.log(news)
var html='';
for (var i = 0; i < news.length; i++) {
if(!news[i]){continue}
html+='<li>'+news[i]+'</li>';
}
console.log(html);
$('.content').innerHTML=html;
}
function $(id){
return document.querySelector(id);
}
</script>
</body>
</html>
router.js
app.get('/getNews', function(req, res) {
var news=[
"上海现史诗级骂街",
"小学课文又现造假",
"巴拉巴拉小魔仙",
"网红渔网袜",
"潮流喇叭裤"
]
var data = [];
for(var i=0;i<3;i++){
var index = parseInt(Math.random()*news.length);
data.push(news[index]);
news.splice(index,1);
}
res.header('Access-Control-Allow-Origin',"http://b.jrg.com:8080");
res.send(data);
})
实现效果
(三)利用降域实现跨域
jiangyua.html
<!DOCTYPE html>
<html>
<head>
<title>降域实现跨域</title>
<meta charset="UTF-8">
<style type="text/css">
input{
margin: 20px;
width: 200px;
}
.container{
width: 1010px;
margin: 0 auto;
}
.main{
width: 500px;
height: 300px;
border:1px solid #eee;
float: left;
}
iframe{
width: 500px;
height:300px;
border:1px dashed #666;
float:right;
}
</style>
</head>
<body>
<div class="container">
<h1>使用降域实现跨域</h1>
<div class="main">
<input type="text" placeholder="http://a.jrg.com:8080/jiangyua.html">
</div>
<iframe src="http://b.jrg.com:8080/jiangyub.html" frameborder="0">
</iframe>
</div>
<script type="text/javascript">
document.querySelector('.main input').addEventListener('input',function(){
console.log(this.value);
window.frames[0].document.querySelector('input').value=this.value;
})
document.domain="jrg.com";
</script>
</body>
</html>
jiangyub.html
<!DOCTYPE html>
<html>
<head>
<title>降域实现跨域</title>
<meta charset="UTF-8">
<style type="text/css">
html,body{
margin:0;
}
input{
margin: 20px;
width: 200px;
}
</style>
</head>
<body>
<input id="input" type="text" placeholder="http://b.jrg.com:8080/jiangyub.html">
<script type="text/javascript">
document.querySelector('#input').addEventListener('click',function(){
window.parent.document.querySelector('input').value=this.value;
})
document.domain='jrg.com';
</script>
</body>
</html>
实现效果
(四)利用postMessage实现跨域
postMessage-a.html
<!DOCTYPE html>
<html>
<head>
<title>降域实现跨域</title>
<meta charset="UTF-8">
<style type="text/css">
input{
margin: 20px;
width: 200px;
}
.container{
width: 1010px;
margin: 0 auto;
}
.main{
width: 500px;
height: 300px;
border:1px solid #eee;
float: left;
}
iframe{
width: 500px;
height:300px;
border:1px dashed #666;
float:right;
}
</style>
</head>
<body>
<div class="container">
<h1>使用降域实现跨域</h1>
<div class="main">
<input type="text" placeholder="http://a.jrg.com:8080postMessage-a.html">
</div>
<iframe src="http://localhost:8080/postMessage-b.html" frameborder="0">
</iframe>
</div>
<script type="text/javascript">
$('.main input').addEventListener('input',function(){
console.log(this.value);
window.frames[0].postMessage(this.value,'*');})
window.addEventListener('message',function(e){
$('.main input').value=e.date;
console.log(e.date);
})
function $(id){
return document.querySelector(id);
}
</script>
</body>
</html>
postMessage-b.html
<!DOCTYPE html>
<html>
<head>
<title>降域实现跨域</title>
<meta charset="UTF-8">
<style type="text/css">
html,body{
margin:0;
}
input{
margin: 20px;
width: 200px;
}
</style>
</head>
<body>
<input id="input" type="text" placeholder="http://b.jrg.com:8080/postMessage-b.html">
<script type="text/javascript">
document.querySelector('#input').addEventListener('input',function(){
window.parent.postMessage(this.value,'*');
})
window.addEventListener('message',function(e){
document.querySelector('#input').value=e.data
console.log(e.data);
})
</script>
</body>
</html>
实现效果