同源策略和跨域

同源策略和跨域

因为同源策略的限制,不同域名,协议(http/https)或者端口无法直接进行ajax请求。
同源策略只针对浏览器端,浏览器一旦检测到跨域后会阻塞请求的结果。
!!跨域的请求是可以发出去的,但是在相应的时候reponse被浏览器阻塞了
跨域的ajax不会携带cookie 但是script/img/iframe 标签是支持跨域的(请求的时候会携带cookie)

csrf攻击(跨站请求伪造)

  1. 如果一个用户登录了abank.com那么cookie里就有了token,同时打开了另一个标签页,页面里有一个iframe如下
    <iframe src="http://abank.com/app/transferFunds?amount=1500&dstAccount=..."></iframe>
    这个iframe的src是上一个页面abank.com的转账请求,如果abank.com的转账请求没有第二重加密措施,那么转账请求就成功了

  2. 路由器的配置,加入在网上找到一个路由器的配置教程的网站。这个网站里偷偷的加一个img标签,如下
    <img src="http://192.168.1.1/admin/config?nexthop=123.12.12.23" style="display:none">
    其中192.168.1.1是很多路由器的配置地址。这个图片被隐藏了,但是请求还是发送出去了。这个请求给路由器添加了一个vpn代理,指向黑客的服务器。如果路由器也是把信息放在了cookie里,这个vpn的请求可能就成功了,以后每个请求都会被监控

跨域请求

  1. 设置请求头
    response.writeHead(200,{"Access-Control-Allow-Origin":"*"})
    在nodejs服务里添加这个头,那么所有的网站都能正常进行跨域请求,还可以指定请求的方式,时间等

  2. jsonp
    另外一个常用的解决方法就是jsonp,这个方法的原理是告诉服务器回调函数的名称,服务器返回的script里面调用这个回调函数,同时传进客户端需要的数据,

客户端脚本
<script>
    function writeDate(data){
        document.write(data)
    }
</script>
<script src="//192.168.0.103:8080/getDate?callback=writeDate"></script>


//服务器脚本
function getDate(response,callback){
    response.writeHead(200,{"Content-Type":"text/javascript"})
    var date = new Date()
    response.end(callback + "('"+data+"')")
}
  1. 子域跨父域

子域跨父域是支持的,但是需要显示将子域的域名改成父域的,例如 mail.qiphon.site 要访问 qiphon.site 的 iframe数据,那么在 mail.qiphon.site脚本里需要执行如下代码
document.domain = "qiphon.site"
这样就可以和父域进行交互了,但是向父域发请求还是跨域的,因为这种更改 domain只是支持client side,并不是client to server 的

  1. iframe 跨父窗口

iframe与父窗口也有同源策略的限制,父域无法直接读取不同源的iframe的dom内容以及监听事件,但是iframe可以调用父窗口提供的api。iframe通过window.parent得到父窗口的window对象,然后父窗口定义一个全局对象提供iframe调用
例如在页面内通过iframe的方式嵌入一个第三方的视频,如果需要手动播放视频、监听iframe的播放事件,页面需要引入第三方的视频播放控制api,在这个js文件里面定义了一个全局的对象YT,如下

if(!window["YT"]){
    var YT = {loading:0,loaded:0}
}   

在视频iframe的脚本里通过window.parent获取得到父窗口即自己网站的页面如下

sr = new Cq(window.parent,d,b)

自己网站也是在这个YT对象自定义一些东西,如添加播放事件监听

new YT.player('video',{events:{'onStateChange':function(data){//do sth.}}})

这样,一旦子域发生了相关的事件,就可以通过window.parent.YT 去调用父域添加的回调函数这样就解决了iframe跨域的问题

  1. window.postMessage

上面的方法,父窗口无法向不同源iframe传递东西,通过window.postMessage可以做到父窗口向iframe传递一个消息,而iframe监听消息事件
例如在8000 的 端口下添加一个9000 的端口的iframe

<iframe src="http://server.com:9000"></iframe>

然后8000端口即父窗口post一个message,

window.onload = function(){
    window.frames[0].postMessage("hello,this is from 8000","http://server.com:9000")
}

postMessage执行的上下文必须是接收信息的window,传递2个参数,第一个是数据,第二个是目标窗口。同时,iframe即9000端口的页面监听事件

window.addEventListener("message",receiveMessage)

function receiveMessage(event){
    var origin = event.origin || event.originalEvent.origin
    //身份验证
    if(origin !=== "http://localhost:8000"){
        return;
    }
    console.log("receiveMessage:"+event.data)
}

这样子iframe就可以收到父窗口的信息了,同理,iframe也可以向父窗口发送消息

window.parent.postMessage("hello this from 9000","http://server.com:8000")

postMessage也适用于通过window.open打开的子窗口,方法类似
补充: 如果iframe 与 父窗口是同源的,则父窗口可以直接获取到iframe的内容,这个方法常用于无刷新上传文件

猜你喜欢

转载自blog.csdn.net/qiphon3650/article/details/81208069