面试之跨域与安全

今天接到了滴滴的一面电面,希望这次可以通过啊,真的不想再死于一面了。

面试过程中有几处没有答出来,其中一个就是跨域,只讲了JSONP和CORS(跨域资源共享),CORS也只是模模糊糊答了一部分,个人感觉并没有达到点上。

回去又好好看了一下,发现还真的有好多可以说的啊,那现在就让我们开始吧~

同源策略

”不同源的站点之间相互请求会做限制“是浏览器的行为,同源指的是协议、域名、端口都相同,脚本不能访问不同源的资源。

前端解决跨域问题

①document.domain+ iframe

只有子域名向父域名请求时才可以用,而且iframe还要设置display为none,底下的代码中document.domain设置此时的主域名。什么是主域名呢?主域名只有一个点号:'a.com'类似这种。与之相对的是子域名:'script.a.com'可以有好几个点号。

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://www.script.a.com/b.html';
ifr.display = none;
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    //在这里操作doc,也就是b.html
    ifr.onload = null;
};

②location.hash+iframe

改变hash值并不会导致页面刷新,所以可以利用hash值来进行数据传递。a.com主域名下的cs1.html要和b.com主域名下的cs2.html进行数据传递,cs1.html创建一个隐藏的iframe(src指向cs2.html),此时的hash值可以用来传递数据(小);cs2.html收到数据后可以通过修改cs1.html的hash值来传递数据,同时cs1.html上有一个定时器,隔一段时间判断location.hash的值有没有变化,一旦有变化就获取hash。

        // a.com域名下的cs1.html
        function srartRequest(){
            var ifr = document.createElement('iframe');
            ifr.style.display = 'none';
            ifr.src = 'http://b.com/cs2.html';
            document.body.appendChild(ifr);
        }
        function checkHsh(){
            try{
                var data = location.hash?location.hash.substring(1):'';
                console.log('The data is'+data);
            }catch(e){
                console.log('The error is'+e);
            }
        }setInterval(checkHsh,2000);
        // b.com域名下的cs2.html
        switch(location.hash){
            case '#123': 
                callback();
                break;
            case '#456':
                //do sth
                break;
        }
        //回调函数用于修改location.hash
        function callback(){
            try {
                parent.location.hash = '一些data';
            }catch(e){
                //ie chrome下无法自己改parent的hash所以还是要借助一个iframe
                var ifr = document.createElement('iframe');
                ifr.style.display = 'none';
                ifr.src = 'http://a.com/cs3.html';
                document.body.appendChild(ifr); 
            }
        }
        //在a.com的cs3.html中
        parent.parent.location.hash = self.location.hash.substring(1);

 ③postMessage

HTML5中新增的方法,实现跨域通信。

//发送窗口
var iframe = window.frames["sendMessage"];
//使用iframe的window向iframe发送message
iframe.onload = function(){
    iframe.postMessage('给你钱儿砸', "*");
}
window.onmessage = function(e){
    alert(e.data);
}        

这里有两个坑,一个是必须运行在服务器环境下,一个是对iframe的postMessage必须等到iframe已经load完,否则无效。

发送的方法为otherWindow.postMessage(message, targetOrigin)。其中otherWindow就是目的窗口,targetOrigin就是目的域。

//接收窗口
window.addEventListener('message',function(e){
    console.log(e.source, e.data, e.origin);
        e.source.postMessage("收到了爹", e.origin);
}, false) 

接收的方法为监听message事件,获取事件event的data、source和origin属性。source就对应发送方窗口,而origin就对应发送方的域。


④WebSocket

HTTP:通信只能由客户端发起,无法做到服务器主动向客户端推送消息。

WebSocket也是基于TCP协议的,服务器端好实现;默认端口也是80(HTTP)和443(HTTPS),握手阶段采用的是HTTP,所以可以通过各种HTTP代理服务器;数据小;没有同源限制。

        //1.新建WebSocket实例,客户端与服务器进行连接
        var ws = new WebSocket("http://a.com/cs1.html");
        //2.onopen属性指定连接成功后的回调函数
        ws.onopen = function(){
            //do sth
            ws.send('These are some data');
        };
        //3.onmessage属性指定收到服务器数据之后的回调函数
        ws.onmessage = function(event){
            var data = event.data;
            //处理数据
        };
        //4.onclose指定连接关闭之后的回调函数
        ws.onclose = function(){
            //do sth
        }
        //5.bufferedAmount表示还有多少字节的二进制数据没发出去
        if(ws.bufferedAmount === 0){
            //发送完毕
        }else{
            //发送还未完成
        }
        //6.onerror指定报错时的回调函数
        ws.onerror = function(){
            //do sth
        }

JS创建了WebSocket之后会发送一个HTTP请求到服务器,取得响应后建立的连接会直接从HTTP变为WebSocket协议。

接下来我们说安全问题~

XSS攻击 :有三方“用户、服务器、攻击者”,攻击者在用户所访问的网页中插入自己的脚本,这段脚本会在用户浏览器中执行,攻击者从而获取用户(比如cookie)信息。因为最后把用户信息发到攻击者自己的网站(和服务器不是一个站),所以叫跨站脚本攻击。

存储型: 数据库中存有的数据,被XSS攻击,返回给客户端。攻击者通过留言、评论、博客的方式,将恶意代码注入到服务器。

反射型:用户输入的,被XSS攻击,发送给后台,后台并未存储也并未过滤,直接“反射”给了客户端。一般攻击者会发送邮件或者聊天软件,用户点击,从而达到XSS攻击。

DOM:根据用户的输入动态构建dom,如果没有对用户的输入进行过滤就会导致受到XSS攻击。DOM-XSS是通过url传入参数控制触发的。

XSS防御办法:

a.对输入和url参数进行过滤,将容易导致XSS攻击的半角字符替换成全角,黑名单就是谁不能出现,白名单就是只能出现谁。前端后端都要过滤。

b.对输出进行转义,对潜在威胁的字符使用编码或者转义的方式,&<>"'/等字符。

c.带有HttpOnly属性的Cookie浏览器可以访问,js脚本不能访问。

CSRF攻击:用户打开浏览器访问信任网站A并输入了用户名和密码,A返回用户Cookie信息。此时用户在没有登出A网站的情况下在同一个浏览器中打开了网站B,B返回一些攻击代码并向A发出请求。这个请求因为是带着用户的Cookie,所以网站A会误认为是用户发来的从而接受请求。

CSRF防御办法:

a.验证HTTP Referer字段。记录该HTTP请求的来源地址。比如银行转账,我们只有先登录账号,才能进行转账,那进行转账时的请求头Referer字段一定是这个网站的名字;而如果是攻击者,他的请求头Referer字段一定是他们自己的地址。

b.给HTTP头增加自定义属性token。还拿转账来打比方吧。登录银行网站时服务器会签发一个token并发给客户端,客户端每次发送请求时都会带着这个token,服务器会进行验证。

c.二维码

猜你喜欢

转载自blog.csdn.net/weixin_40322503/article/details/80009591