同源策略

2017-08-02  本文已影响117人  DCbryant

题目1: 什么是同源策略

同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。

浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。

所谓"同源"指的是"三个相同"。

示例:
http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。它的同源情况如下。

题目2: 什么是跨域?跨域有几种实现形式

跨域是指从一个域名的网页去请求另一个域名的资源。比如从http://www.baidu.com/页面去请求https://www.zhihu.com 的资源。跨域的严格一点的定义是:只要 协议,域名,端口有任何一个的不同,就被当作是跨域。

有8种方法:

若想了解详细情况,请仔细阅读这篇文章,很赞!!!

题目3: JSONP 的原理是什么

前端:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div class="container">
        <ul class="news">
            <li>233</li>
            <li>323</li>
            <li>332</li>
        </ul>
        <button class="change">换一组</button>
    </div>

    <script>
        let $ = (className) => document.querySelector(className)

        $('.change').addEventListener('click',function(){
            var script = document.createElement('script')
            script.src = 'http://localhost:8080/getNews?callback=appendHtml'
            document.head.appendChild(script)
            document.head.removeChild(script)
        })
        // appendHtml(["321","987","159"])
        function appendHtml(news){
            var html = ''
            for(var i=0;i<news.length;i++){
                html += '<li>' + news[i] + '</li>'
            }
            console.log(html)
            $('.news').innerHTML = html
        }
    </script>
</body>
</html>
后端;
app.get('/getNews',function(req,res){
    var news = [
        '123',
        '456',
        '789',
        '321',
        '654',
        '987',
        '753',
        '159',
        '852'
    ]
    var data = []
    for(var i=0;i<3;i++){
        var index = parseInt(Math.random() * news.length)
        data.push(news[index])
        news.splice(index,1)
    }
   
    var cb = req.query.callback
    var show = cb + '(' + JSON.stringify(data) + ')'
    console.log(show)
    if(cb){
        res.send(show)
    }else{
        res.send(data)
    }
})

题目4: CORS是什么

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS 存在以下三种主要场景,分别是简单请求,预检请求和附带身份凭证的请求

1.简单请求:若只使用 GET, HEAD 或者 POST 请求,且除 CORS 安全的首部字段集合外,无人为设置该集合之外的其他首部字段,同时 Content-Type 值属于下列之一,那么该请求则可以被视为简单请求:

application/x-www-form-urlencodedmultipart/form-datatext/plain

此情况下,若服务端返回的 Access-Control-Allow-Origin: *,则表明该资源可以被任意外域访问。若要指定仅允许来自某些域的访问,需要将*设定为该域,例如:Access-Control-Allow-Origin: http://foo.example

2.预检请求:与前述简单请求不同,该要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。当请求满足以下三个条件任意之一时, 即应首先发送预检请求:

application/x-www-form-urlencodedmultipart/form-datatext/plain

预检请求完成之后(通过 OPTIONS 方法实现),才发送实际请求。一个示范 HTTP 请求如下所示:

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '<?xml version="1.0"?><person><name>Arun</name></person>';
    
function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body); 
    }
}

3.附带身份凭证的请求:这种方式的特点在于能够在跨域请求时向服务器发送凭证请求,例如 Cookies (withCredentials 标志设置为 true)。

一般而言,对于跨域 XMLHttpRequest 或 Fetch 请求,浏览器不会发送身份凭证信息。如果要发送凭证信息,需要设置 XMLHttpRequest 的某个特殊标志位。但是需要注意的是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true,浏览器将不会把响应内容返回给请求的发送者。

附带身份凭证的请求与通配符
对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为*
这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为*,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为 http://foo.example,则请求将成功执行。
另外,响应首部中也携带了 Set-Cookie 字段,尝试对 Cookie 进行修改。如果操作失败,将会抛出异常。

MDN 引例如下:

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';
    
function callOtherDomain(){
  if(invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    invocation.send(); 
  }
}

题目5: 根据视频里的讲解演示三种以上跨域的解决方式 ,写成博客

跨域

参考链接:

上一篇 下一篇

猜你喜欢

热点阅读