精华内容
下载资源
问答
  • 同源策略
    千次阅读
    2022-03-21 13:37:54

            跨域问题涉及到WEB网页安全性问题,使用不当会造成用户隐私泄露风险,但有时业务上又需要进行跨域请求。如何正确的使用跨域功能,既能满足业务需求,又能够满足安全性要求,显得尤为重要。

    1.1.同源策略

    • 协议相同
    • 域名相同
    • 端口相同

    同源策略限制内容有:

    • Cookie、LocalStorage、IndexedDB 等存储性内容
    • DOM 节点
    • AJAX 请求发送后,结果被浏览器拦截了

    同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。

            1.2.为什么要有跨域限制

    Ajax 的同源策略主要是为了防止 CSRF(跨站请求伪造) 攻击,如果没有 AJAX 同源策略,相当危险,我们发起的每一次 HTTP 请求都会带上请求地址对应的 cookie,那么可以进行攻击。

    其实,准确的来说,跨域机制是阻止了数据的跨域获取,不是阻止请求发送。

    2.浏览器跨域的解决方案

            2.1.CORS标准

    CORS 是一个 W3C 标准,全称是跨域资源共享(CORSs-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求。

                    2.1.1.简单请求

    只要同时满足以下两大条件,就属于简单请求

    条件1:使用下列方法之一:

    • GET
    • HEAD
    • POST

    条件2:Content-Type 的值仅限于下列三者之一:

    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded

    请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器; XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。

                    2.1.2.复杂请求

    不符合以上条件的请求就肯定是复杂请求了。 复杂请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求,该请求是 option 方法的,通过该请求来知道服务端是否允许跨域请求。

    我们用 PUT向后台请求时,属于复杂请求,后台需做如下配置:

    // 允许哪个方法访问我
    res.setHeader('Access-Control-Allow-Methods', 'PUT')
    // 预检的存活时间
    res.setHeader('Access-Control-Max-Age', 6)
    // OPTIONS请求不做任何处理
    if (req.method === 'OPTIONS') {
      res.end() 
    }
    // 定义后台返回的内容
    app.put('/getData', function(req, res) {
      console.log(req.headers)
      res.end('我不爱你')
    })

    接下来我们看下一个完整复杂请求的例子,并且介绍下CORS请求相关的字段

    // index.html
    let xhr = new XMLHttpRequest()
    document.cookie = 'name=xiamen' // cookie不能跨域
    xhr.withCredentials = true // 前端设置是否带cookie
    xhr.open('PUT', 'http://localhost:4000/getData', true)
    xhr.setRequestHeader('name', 'xiamen')
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
          console.log(xhr.response)
          //得到响应头,后台需设置Access-Control-Expose-Headers
          console.log(xhr.getResponseHeader('name'))
        }
      }
    }
    xhr.send()
    //server1.js
    let express = require('express');
    let app = express();
    app.use(express.static(__dirname));
    app.listen(3000);
    //server2.js
    let express = require('express')
    let app = express()
    let whitList = ['http://localhost:3000'] //设置白名单
    app.use(function(req, res, next) {
      let origin = req.headers.origin
      if (whitList.includes(origin)) {
        // 设置哪个源可以访问我
        res.setHeader('Access-Control-Allow-Origin', origin)
        // 允许携带哪个头访问我
        res.setHeader('Access-Control-Allow-Headers', 'name')
        // 允许哪个方法访问我
        res.setHeader('Access-Control-Allow-Methods', 'PUT')
        // 允许携带cookie
        res.setHeader('Access-Control-Allow-Credentials', true)
        // 预检的存活时间
        res.setHeader('Access-Control-Max-Age', 6)
        // 允许返回的头
        res.setHeader('Access-Control-Expose-Headers', 'name')
        if (req.method === 'OPTIONS') {
          res.end() // OPTIONS请求不做任何处理
        }
      }
      next()
    })
    app.put('/getData', function(req, res) {
      console.log(req.headers)
      res.setHeader('name', 'jw') //返回一个响应头,后台需设置
      res.end('我不爱你')
    })
    app.get('/getData', function(req, res) {
      console.log(req.headers)
      res.end('我不爱你')
    })
    app.use(express.static(__dirname))
    app.listen(4000)

            2.2.JSONP跨域

     Script不受浏览器同源策略的影响,所以通过 Script 便签可以进行跨域的请求:

    1. 首先前端先设置好回调函数,并将其作为 url 的参数。
    2. 服务端接收到请求后,通过该参数获得回调函数名,并将数据放在参数中将其返回
    3. 收到结果后因为是 script 标签,所以浏览器会当做是脚本进行运行,从而达到跨域获取数据的目的。
    //后端逻辑
    var url = require('url')
    var http = require('http')
    http.createServer(function (req, res) {
        var data = {
            name: "haha"
        };
        var callback = url.parse(req.url,true).query.callback;
        //url.parse(req.url,true).query即{callback:jsonpCallback} ----------------获取函数名callback
        res.writeHead(200)
        res.end(`${callback}(${JSON.stringify(data)})`)
    
    }).listen(3000, '127.0.0.1')
    //服务端接收到请求后获取到回调函数名callback,将数据放在参数中将其返回,即返回callback({"name" : "haha"}) 函数调用
    console.log('监听127.0.0.1:3000端口')  //注意这里文字一定要引号包裹不然会报错
    //注意终端提示:SyntaxError: Invalid or unexpected token 无效或意外的标记,出现这种情况一般是中文的标点符号或者漏写了符号导致的
    <!--前端页面-->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>JSONP实现跨域</title>
    </head>
    <body>
        <script>
           function jsonpCallback(data) {
               console.log(JSON.stringfy(data))
           }   //定义回调函数jsonpCallback,收到服务端返回结果callback({"name" : "haha"}),callback=jsonpCallback
        </script>
        <script src="http://127.0.0.1:3000?callback=jsonpCallback"></script>  //web页面上调用js文件不收同源策略影响
    
    </body>
    </html>

            2.3.nginx反向代理

    实现原理类似于Node中间件代理,需要你搭建一个中转nginx服务器,用于转发请求。

    使用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。

    实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

    先下载nginx,然后将nginx目录下的nginx.conf修改如下:

    // proxy服务器
    server {
        listen       80;
        server_name  www.domain1.com;
        location / {
            proxy_pass   http://www.domain2.com:8080;  #反向代理
            proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
            index  index.html index.htm;
    
            # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
            add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
            add_header Access-Control-Allow-Credentials true;
        }
    }

    最后通过命令行 nginx-s reload启动nginx

    // index.html
    var xhr = new XMLHttpRequest();
    // 前端开关:浏览器是否读写cookie
    xhr.withCredentials = true;
    // 访问nginx中的代理服务器
    xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
    xhr.send();
    // server.js
    var http = require('http');
    var server = http.createServer();
    var qs = require('querystring');
    server.on('request', function(req, res) {
        var params = qs.parse(req.url.substring(2));
        // 向前台写cookie
        res.writeHead(200, {
            'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本无法读取
        });
        res.write(JSON.stringify(params));
        res.end();
    });
    server.listen('8080');
    console.log('Server is running at port 8080...');

    更多相关内容
  • js同源策略详解

    2020-12-10 21:33:46
    本文较为详细的分析了js同源策略。分享给大家供大家参考。具体如下: 概念:同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个...
  • 1. 什么是同源策略   理解跨域首先必须要了解同源策略同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。  何谓同源:  URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则...
  • 但是在开发过程中遇见了同源策略的跨域问题,页面能够显示,但是却没有数据,显示如下 右键检查报错如下: 报错代码如下 Failed to load http://127.0.0.1:8888/publisher/: No 'Access-Control-Allow-Origin' ...
  • **同源策略**是指在[Web浏览器](https://zh.wikipedia.org/wiki/排版引擎)中,允许某个网页[脚本](https://zh.wikipedia.org/wiki/腳本)访问另一个网页的数据,但前提是这两个网页必须有相同的[URI]...
  • 同源策略

    千次阅读 2019-04-19 09:26:16
    0x00 同源策略简介: 什么是同源策略同源策略是禁止javascript进行跨域访问的安全策略,他是浏览器的沙盒环境所提供的一项制约。 什么是相同源:源是一个由<协议,主机,端口>构成的三元组,而两个相同...

    0x00 同源策略简介:

    • 什么是同源策略:同源策略是禁止javascript进行跨域访问的安全策略,他是浏览器的沙盒环境所提供的一项制约。

    • 什么是相同源:源是一个由<协议,主机,端口>构成的三元组,而两个相同源需要这个三元组的所有属性都相同。
      举个栗子:出自MDN文档在这里插入图片描述

    • 同源策略的好处:限制一个源的脚本从另外一个源加载资源的行为,在对恶意脚本的防护上起到巨大的作用。ps:需要注意的是,同源策略不是禁止脚本的执行,而是禁止读取HTTP的响应。也就是跨域的资源访问请求是允许的,但是服务端返回的数据是禁止读取的。

    0x01 跨域网络访问

    同源策略限制了两个不同源之间的相互作用,例如你使用的XMLHttpRequest或者元素。一般来说跨域的请求行为分为三种:

    1、Cross-origin writes are typically allowed. Examples are links, redirects, and form submissions. Some HTTP requests require preflight.(通常允许进行跨域写,例如links,重定向,表单提交等等。一些HTTP请求要求进行预检)
    2、Cross-origin embedding is typically allowed. (Examples are listed below.)
    3、Cross-origin reads are typically disallowed, but read access is often leaked by embedding. For example, you can read the dimensions of an embedded image, the actions of an embedded script, or the availability of an embedded resource.
    

    哪些资源是允许嵌入的:
    翻译太难搞了,截图简单

    0x02 如何进行跨域资源访问:

    虽然同源策略对恶意脚本的防护是必要的,但是当我们需要合理的跨域资源访问时,要如何实现:

    • JSONP跨域请求:这不是重点,所以略过。

    • CORS跨域请求:

    1、CORS 的全称是cross-origin sharing stander,跨域资源共享标准。
    在这里插入图片描述

    2、跨域访问时HTTP请求包与响应包结构:在这里插入图片描述
    左侧的Origin字段表示的是请求页面所在的域。
    右侧Access-Control-Allow-Origin是响应头,用于标识允许请求的域。只有当左侧的请求域属于右侧字段定义的域的子域才能进行跨域通信。
    在这里插入图片描述
    此时根据上课的大佬解释,存在CORS漏洞,可以获取到敏感信息,具体自己去看视频吧,菜鸡就不解释了:https://www.bilibili.com/video/av38650052?t=120 <b站漏洞银行咖面>
    小声bb:有点跑题,以后一定要再写一篇博客。

    3、这个标准允许在以下的几个场景中发起跨域请求:

    由XMLHttpRequest或Fetch等发起的跨域请求;
    Web 字体,通过 @font-face 进行跨域调用;
    WebGL 贴图;
    使用 drawImage 将 Images/video 画面绘制到 canvas;
    样式表(使用 CSSOM);
    scripts;
    

    4、CORS进阶:菜鸡已经写不清楚了,所以就转一个大佬的博客吧【菜哭】

    • CORS通过一些特殊的 HTTP 头来确保哪些源站可以请求哪些资源,除此之外,如果这个请求会对服务器的数据产生修改的可能(这个说法并不是很准确,后面会详细阐述),将会在跨域之前发起一个preflight请求进行检查,如果检查不通过,那么不会发起跨域请求。

    • 首先要明确一点,并不是所有的请求都会触发preflight机制,这些不会触发preflight的请求被称为simple request。
      符合下列条件的请求,将不会触发preflight机制并视为simple request:

      • GET 请求
      • HEAD 请求
      • Content-Type 为指定值的 POST 请求,包括text/plain,multipart/form-data以及application/x-www-form-urlencode
      • HTTP 首部字段不能包含下列以外的值:
        Accept
        Accept-Language
        Content-Language
        Content-Type
        DPR
        Downlink
        Save-Data
        Viewport-Width
        Width
    • 凡是不满足上述条件的请求,将被视为preflight request,并在发起跨域请求前,预先发起一个OPTIONS请求进行检查。在preflight request的返回头中,会包含一些关于是否允许发起跨域的信息。例如我们看这个preflight的例子,这个是向一个地址 POST XML 内容的请求:
      在这里插入图片描述

    在OPTIONS请求中,发出了两个特殊的 HTTP 头,分别是Access-Control-Request-Method和Access-Control-Request-Headers,意思是告诉服务端,我接下来的请求中,会使用POST方法,并且会携带两个自定义的头部字段X-TEST和Content-Type(因为Content-Type的内容并非是我们上文中提到的三种之一,所以被看做是自定义头部)。

    在返回头中,要注意四个字段:
    在这里插入图片描述
    从第一行开始,表示允许来自(http,foo.example,80)这个源发来的数据,允许的方法为POST,GET,OPTIONS,允许使用自定义的头部X-TEST和Content-Type,该响应的有效时间是86400秒,如果在这个期间内,客户端无需为了同样的跨域请求再次发起preflight request,通常情况下,每个浏览器都有自己的最大时间以避免出现某些安全问题。

    最后呢,神奇的是 CORS 还允许通过设置 Cookies 或 HTTP 认证来发送认证信息。如果发起的是一个简单请求,那么不会经过preflight,但是有一点需要注意,如果服务端返回的信息中没有Access-Control-Allow-Credentials: true,浏览器就会拦截返回内容,不会将内容返还给调用者。

    0x03 同源策略实验:

    环境:
    <><>请求域:www.hnust.fun
    <><>目标域:www.xss.com

    1. 首先在目标域中不添加跨域头:Access-Control-Allow-Origin
      在这里插入图片描述
      这种情况下进行跨域资源访问,会被浏览器拦截。
    2. 在请求域使用如下脚本进行跨域访问:
    <html>  
    <head> 
    <meta charset="utf-8"/>
    <script type="text/javascript">  
    //创建 XMLHttpRequest 对象  
    var xmlhttp;  
    if (window.XMLHttpRequest)  
      {// code for IE7+, Firefox, Chrome, Opera, Safari  
      xmlhttp=new XMLHttpRequest();  
      }  
    else 
      {// code for IE6, IE5  
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");  
      }  
    //每当 readyState 改变时,就会触发 onreadystatechange 事件  
    xmlhttp.onreadystatechange=function()  
      {  
       //当 readyState 等于 4 且状态为 200 时,表示响应已就绪  
      if (xmlhttp.readyState==4 && xmlhttp.status==200)  
        {  
         //处理服务器的响应  
    		alert("好了,又坑了一个人!!!");    //每当跨域请求成功会弹出对话框
        }  
      }  
    xmlhttp.open("GET","http://www.xss.com/index.php?page=system&option=question"); 
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.send();
    </script>  
    </head>  
    <body>  
      <h1>欢迎光临啊!!!</h1>
    </body>
    </html>
    

    在上面的代码中向目标域发起一次get请求,如果请求成功会弹出一个对话框。效果如下:
    在这里插入图片描述
    可以看到同源策略禁止读取,而且没有弹出对话框。
    3. 将目标域的头设置打开。
    在这里插入图片描述
    先设置只允许www.hnust.fun发起跨域请求,等下测试其他跨域请求是否被允许。
    4. 再次发起跨域请求,这次发起请求的时候会在HTTP消息头中添加字段Origin,用来标识请求域:
    在这里插入图片描述
    结果请求成功:
    在这里插入图片描述
    在实验中有一点重要,origin的的值必须域ACAO头完全一致,或者ACAO是*的通配符,否则跨域失败。
    在这里插入图片描述
    5. ps:有一点很重要,同源策略只是限制了浏览器读取请求,但是不会限制请求的进行,也就是说我们发起请求是不受同源策略限制的,这也符号之前的一个实验,向目标域使用ajax提交了一条留言,虽然没有弹出留言提交成功,但是留言确实插入了目标域。这是因为,弹出留言对话框这个操作是受浏览器同源策略限制的,而提交留言的请求不受限制。

    0x04:参考博文

    1、https://lightless.me/archives/review-SOP.html#_label4
    2、https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
    3、https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control
    
    展开全文
  • 同源策略与跨域

    千次阅读 2021-11-21 17:07:13
    前言:最近业务上前端同学多次联系说访问腾讯云cos资源的时候因为跨域的...同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;关于这一点我们后面会举例说明。...

    前言:最近业务上前端同学多次联系说访问腾讯云cos资源的时候因为跨域的问题访问不到。大致看了下腾讯云关于设置跨域访问的教程,按照前端同学给的域名等选项就给配了,而且测试下来也是好的。但是呢一直不知道什么是跨域这里就做一个简单的学习记录。

    一、同源策略

            同源策略(Same Origin Policy)是一种约定,它是浏览器最核心也是最基本的安全功能。同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;关于这一点我们后面会举例说明。如果缺少了同源策略浏览器的安全使用会受到很大的影响。可以说web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

    1、同源的定义

    当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

    如下表给出了相对http://www.example.com/dir/page.html的同源检测示例:

    URL结果原因
    http://www.example.com/dir2/other.html成功协议、域名、端口相同
    http://www.example.com/dir/inner/another.html成功协议、域名、端口相同
    https://www.example.com/secure.html失败协议不同 ( HTTPS )
    http://www.example.com:81/dir/etc.html失败端口不同 ( 81 )
    http://news.example.com/dir/other.html失败域名不同

    同源策略目的就是为了保证用户信息的安全,防止恶意的网站窃取用户数据。如果网页之间不满足“同源”的要求,那么它们之间:

    (1)不能共享Cookie、LocalStorage、IndexDB
    (2)不能获取DOM
    (3)AJAX请求不能发送

     

    2、同源策略作用举例

            下面举一个例子说明针对接口的请求没有同源策略会怎么样?

            cookie大家应该知道,一般用来处理登录等场景,目的是让服务端知道谁发出的这次请求。如果你请求了接口进行登录,服务端验证通过后会在响应头加入Set-Cookie字段,然后下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中,服务端就能知道这个用户已经登录过了。知道这个之后,我们来看场景:
    1.某11到了,于是打开了买买买网站www.maimaimai.com,然后登录成功,然后准备一番剁手操作。
    2.期间你的好朋友突然给你发了一个你懂得的网站链接www.nidongde.com,一脸yin笑地跟你说:“你懂的”,你毫不犹豫打开了。
    3.你饶有兴致地浏览着www.nidongde.com!由于没有同源策略的限制,它向www.maimaimai.com发起了请求!前面我们说过“服务端验证通过后会在响应头加入Set-Cookie字段,然后下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中”,这样一来,这个不法网站就相当于登录了你的账号,可以为所欲为了!如果这不是一个买买买账号,而是你的银行账号,那……
    这个过程就是就是CRFS(跨站请求伪造)攻击了!!参见 这里

           显然,同源策略是非常重要的。否则网站站长、广告联盟、流量统计商、xss黑客,随便哪个人都将无障碍的获取私密信息,例如各个网站的Cookie、email的邮件内容、OA页面的内容、QQ空间里设置为隐私的照片等。

            

    3、同源策略的让步

        几乎任何时候安全性和便利性都是负相关的,追求安全性的时候肯定会对便利性造成负面影响。同样,同源策略提升了web前端的安全性,但是却牺牲了web扩展上的灵活性。所以,现代浏览器在安全性可可用性之间选择了一个平衡点。即在遵循同源策略的基础上,选择性的为同源策略“开放了后门”。例如img、script、style等变迁都允许跨域引用资源,严格来说这都是不符合同源要求的。只不过这里只是引用这些资源,并不能读取到这些资源的内容。因此浏览器降低了一点点的安全性,缺大大提升了网站布置的灵活性。

    二、跨域问题

            由于同源策略存在带来的问题就是跨域问题了。

    1、跨域访问限制的流程

    同源策略,它是由Netscape提出的一个著名的安全策略。
    所有支持JavaScript 的浏览器都会使用这个策略。
    所谓同源是指,域名,协议,端口相同。
    当一个浏览器的两个tab页中分别打开来 百度和谷歌的页面
    当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,
    即检查是否同源,只有和百度同源的脚本才会被执行。 [1]
    如果非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
    同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。

    如上图所示,跨域访问限制的作用流程大致如下:

    1、 浏览器发送跨域请求
    2、 接收response数据
    3、 检查响应头
    (1)如果响应头中没有允许跨域访问的配置,则不加载,并报出响应异常
    (2)如果响应头中有允许跨域访问的设置,正常加载数据

    即,同源策略并不是浏览器不让请求发出去、或者后端拒绝返回数据。实际情况是请求正常发出去了,后端也正常相应了,只不过数据到了浏览器后浏览器不去作用加载而是丢弃了。

     

    三、跨域问题的解决

    1、JSONP:以后涉及到在说。

    2、CORS(Cross-Origin Resource Sharing)跨域资源共享机制

            简称为跨域访问,允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器要求版本 IE10 或以上。

            整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户无感知。

            因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,即可跨源通信。

    (1)CORS使用场景

            用户在使用浏览器的情况下会使用到 CORS,因为控制访问权限的是浏览器而非服务器。因此使用其它客户端的时候无需关心任何跨域问题

            对于我们遇到的问题来说,CORS 的主要应用是实现在浏览器端使用 AJAX 直接访问 COS 的数据或上传、下载数据,而无需通过用户本身的应用服务器中转。

    (2)CORS原理:

    我们看一眼之前跨域报错的信息:

     浏览器判断后端有没有返回CORS头(Access-Control-Allow-Origin),发现没有就认为后端不允许跨域,即认为返回的数据不可靠。

    所以只要后端能够返回浏览器需要的请求头,即可跨域(相应数据不会被同源策略抛弃)。

    上面是表面原理,底层原理比较复杂。

    浏览器会将ajax请求分为两类,其处理方案略有差异:简单请求、特殊请求。

    简单请求

    只要同时满足以下两大条件,就属于简单请求。:

    (1) 请求方法是以下三种方法之一:

    • HEAD
    • GET
    • POST

    (2)HTTP的头信息不超出以下几种字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

    当浏览器发现发起的ajax请求是简单请求时,会在请求头中携带一个字段:Origin.

    刚才说过,CORS需要客户端和服务端同时支持。上面这个小操作,算是客户端的支持行为(IE10以下不行)。

     

    Origin中会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。

    如果服务器允许跨域,需要在返回的响应头中携带下面信息(算是服务端的支持):

     

    • Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*(代表任意域名)。上图CORS策略配置的允许跨域请求来源是“*”,表示全部域名都允许。
    • Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true

    有关cookie:

    要想操作cookie,需要满足3个条件:

    • 服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。
    • 浏览器发起ajax需要指定withCredentials 为true
    • 响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名

    这样一来,前后端都支持跨域了,那就跨吧。

     

    注意:

    (1)测试截图是根据腾讯云手册的设置实例来的,这里 

    (2)关于web网页的部署,参见 草稿“Linux下的web服务器搭建”。

    (3)另外配置web服务器的时候要注意安全组规则的设置;另外可以通过调整COS的跨域策略对比能否成功跨域在请求和相应方面的差异。

    展开全文
  • 本文实例讲述了JavaScript同源策略和跨域访问。分享给大家供大家参考,具体如下: 1. 什么是同源策略 理解跨域首先必须要了解同源策略同源策略是浏览器上为安全性考虑实施的非常重要的安全策略。 何谓同源: URL由...
  • 浏览器的同源策略它会阻止读取来自不同源的资源。同源策略机制主要用于阻止恶意站点读取另一个站点的数据,让用户安全地上网。

    同源策略

    同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

    浏览器的同源策略它会阻止读取来自不同源的资源。同源策略机制主要用于阻止恶意站点读取另一个站点的数据,让用户安全地上网。

    同源策略是为了保护本地数据不被 JavaScript 代码获取回来的数据污染,拦截的是客户端对于响应的接收,即浏览器请求发送出去了,服务器也响应了,但是响应无法被浏览器接收。

    同源指协议,域名,端口都需要相同。例如相对于 https://www.chenpi.com/index.html 。

    • https://www.chenpi.com/user/add:同源。
    • http://www.chenpi.com/index.html:不同源,协议不同。
    • https://www.chenpi.cn/index.html:不同源,域名不同。
    • https://www.chenpi.com:8081/index.html:不同源,端口不同。

    我们打开百度的页面,然后打开控制台(按 F12),输入以下命令请求京东的首页地址。发现出现了跨域错误。

    fetch("https://www.jd.com/")
    

    在这里插入图片描述

    通过查看请求详情,请求是正常发送出去了,而且服务端也成功响应了,但是请求结果没被浏览器接收。

    在这里插入图片描述

    在这里插入图片描述

    因为浏览器同源策略的存在,所以才出现跨域限制问题。但有时我们不需要这种跨域限制,CORS 就是解决跨域的一种解决方案。还有另外一种跨域解决方案是 JSONP,但是这种只支持 GET 请求,比较受限。

    CORS 简介

    CORS(Cross-Origin Resource Sharing,跨域资源共享),是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制。

    CORS 原理就是在进行访问跨域资源时,浏览器和服务器通过自定义的 HTTP 头部进行协商沟通,从而决定请求或者响应是应该成功还是失败。CORS 需要浏览器和服务器同时支持。几乎所有浏览器都支持此功能,IE 浏览器版本不能低于 IE10。

    CORS 请求模型

    CORS 分为两种请求模型:

    1. 简单请求:支持 head/get/post 请求,请求头信息只能是Accept,Accept-Language,Content-Language,Last-Event-ID,Content-type等标准头部,不支持自定义 header,content-type 值只支持text/plain,application/x-www-urlencoded,multipart/form-data。请求不可以携带 cookie。
    2. 非简单请求,协商模型/预检请求(Preflighted Request):除了简单请求之外,其他就是属于非简单请求。

    这两种请求模型的通信过程如下:

    简单请求:

    1. 浏览器发出的请求添加请求头部 Origin,标识请求页面的源信息(协议,域名,端口号),例如Origin: https://www.chenpi.com
    2. 服务器接收到请求,可检查 Origin 判断此源是否可信任。如果信任允许此源请求服务器的资源,就在响应头中返回Access-Control-Allow-Origin: https://www.chenpi.com。如果是请求的资源是公共资源可直接返回Access-Control-Allow-Origin: *表示允许所有请求源。
    3. 浏览器根据响应头部结果,决定是否接收响应数据。
    4. 默认情况下,请求不可以携带 cookie,如果需要携带,ajax 请求需要设置 xhr 属性 withCredentials 的值为 true,服务器需要设置响应头Access-Control-Allow-Credentials: true

    非简单请求:

    1. 例如浏览器发出 PUT 请求,浏览器会预先发出 OPTIONS 请求,携带请求头Origin: https://www.chenpi.com,Access-Control-Request-Method: PUT,Access-Control-Request-Headers: 自定义的头部字段,多个头部以逗号分隔(可选)
    2. 服务器接收到 OPTIONS 请求,根据请求头信息决定是否响应此请求,如果信任可以在响应头中添加如下信息:
    • Access-Control-Allow-Origin:https://www.chenpi.com
    • Access-Control-Allow-Methods: PUT(允许的方法,多个方法以逗号分隔)
    • Access-Control-Allow-Headers: 允许的头部字段,多个方法以逗号分隔。
    • Access-Control-Max-Age: 预检请求(OPTIONS)可以缓存的最长时间,单位秒。
    1. 预检请求被允许之后,以后每次浏览器正常的 CORS 请求(例如 PUT),就和简单请求过程一样了。

    Spring Boot 实现 CORS

    显示设置头部

    通过 CORS 原理可知,我们只需要在响应头部中添加相应头部信息即可解决跨域问题,如下:

    package com.chenpi.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @Description
     * @Author 陈皮
     * @Date 2022/5/1
     * @Version 1.0
     */
    @RestController
    @RequestMapping
    public class ChenPiController {
    
      @GetMapping("test")
      public JSONObject test(HttpServletResponse httpServletResponse) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "陈皮");
        jsonObject.put("age", 18);
        // 解决跨域
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "https://www.baidu.com");
    //    httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
        return jsonObject;
      }
    
    }
    

    如果需要允许携带 cookie 信息,请求头部和响应头部都添加相应信息。注意,当添加Access-Control-Allow-Credentials: true时,Access-Control-Allow-Origin的值不能设置为星号。

    package com.chenpi.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @Description
     * @Author 陈皮
     * @Date 2022/5/1
     * @Version 1.0
     */
    @RestController
    @RequestMapping
    public class ChenPiController {
    
      @GetMapping("test")
      public JSONObject test(HttpServletResponse httpServletResponse) {
    
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "陈皮");
        jsonObject.put("age", 18);
        // 解决跨域
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "https://www.baidu.com");
        // 允许携带cookie,浏览器跨域使用验证:fetch('http://127.0.0.1:8080/test',{mode: 'cors',credentials: 'include'})
        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
    
        return jsonObject;
      }
    
    }
    

    注解 @CrossOrigin

    对于以上方案,如果要解决跨域的接口比较多,就需要在每个接口都写重复代码。Spring Boot 提供了跨域解决方案,使用注解@CrossOrigin

    @CrossOrigin 注解可作用在单个接口上,或者作用在类上(对类下的所有接口都生效)。

    package com.chenpi.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @Description
     * @Author 陈皮
     * @Date 2022/5/1
     * @Version 1.0
     */
    @RestController
    @RequestMapping
    public class ChenPiController {
    
      @GetMapping("test")
      @CrossOrigin
      public JSONObject test() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "陈皮");
        jsonObject.put("age", 18);
        return jsonObject;
      }
    }
    

    对于 CORS 通信过程用到的 HTTP 头部,@CrossOrigin 注解里面都定义了相应属性,并设置了默认值。

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface CrossOrigin {
    
    	// 默认是*
    	@AliasFor("origins")
    	String[] value() default {};
    
    	@AliasFor("value")
    	String[] origins() default {};
    
    	// 通配符,默认空
    	String[] originPatterns() default {};
    
    	// 默认所有自定义头部都被允许,*
    	String[] allowedHeaders() default {};
    
    	// 默认允许方法和接口定义的请求方式保持一致,例如@GetMapping("test")则值为GET
    	RequestMethod[] methods() default {};
    
        // 默认,Access-Control-Allow-Credentials:false
    	String allowCredentials() default "";
    
        // -1代表默认值1800秒,Access-Control-Max-Age:1800
    	long maxAge() default -1;
    
    }
    

    我们可以修改默认值,并且此注解可以在类中和方法中同时定义,它们会形成互补,即对任意一个头部属性,如果在方法的注解中是默认值,则会再去类上的注解中进行判断,如下:

    package com.chenpi.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @Description
     * @Author 陈皮
     * @Date 2022/5/1
     * @Version 1.0
     */
    @RestController
    @RequestMapping
    @CrossOrigin(origins = {"https://www.baidu.com", "https://www.jd.com"}, allowCredentials = "true"
        , maxAge = 3600)
    public class ChenPiController {
    
      @GetMapping("test")
      public JSONObject test() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "陈皮");
        jsonObject.put("age", 18);
        return jsonObject;
      }
    
      @GetMapping("demo")
      @CrossOrigin(origins = {"https://www.taobao.com"}, allowedHeaders = {"ChenPiHeader"},
          allowCredentials = "false")
      public JSONObject demo() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "陈皮");
        jsonObject.put("age", 20);
        return jsonObject;
      }
    
    }
    

    全局配置

    可以进行全局配置,这样就不需要对每个接口进行单独跨域配置,如下:

    package com.chenpi.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
      @Override
      public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("https://www.baidu.com", "https://www.jd.com")
            .allowCredentials(true).allowedHeaders("chenpi-header")
            .allowedMethods("PUT", "GET", "POST", "HEAD")
            .maxAge(3600);
      }
    }
    

    本次分享到此结束啦~~

    如果觉得文章对你有帮助,点赞、收藏、关注、评论,您的支持就是我创作最大的动力!

    展开全文
  • 协议、域名以及端口号相同就为同源,是由...为什么会有同源策略?简单来说是为了安全 1.为了防止恶意网页可以获取其他网站的本地数据。 2.为了防止恶意网站iframe其他网站的时候,获取数据。 3.为了防止恶意网站在
  • 同源策略保护了什么、如何规避同源限制 基本照抄阮一峰的博客:浏览器同源政策及其规避方法 同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它帮助阻隔...
  • 什么是同源策略

    千次阅读 2022-04-22 01:09:59
    同源策略
  • 中国科学院大学研究生教材,网络空间安全学院名师讲授
  • 同源策略&跨域

    2022-04-21 09:28:32
    了解同源策略&跨域 1.什么是同源 同源指的是两个 URL 地址具有相同的协议、主机名、端口号。 例如,下表给出了相对于 http://www.test.com/index.html 页面的 5 个同源检测结果: 2.什么是同源...
  • 前言提要: ​ 面试的时候被问到了是否了解同源策略,并没有了解过 (虽然朋友洋写了文章,但是我当时也没有仔细琢磨)。所以有了这篇文… ​ 据说了解同源策略是十分有必要的,要深入了解XSS/CSRF等web安全漏洞,不...
  • 同源策略(same origin policy)

    千次阅读 2022-06-18 11:13:56
    同源策略是一个重要的安全策略,它用于限制一个origin的文档或它加载的脚本如何能与另一个源的资源进行交互。能够减少恶意文档,减少可能被攻击媒介。 如果两个URL的协议、域名、端口号都相同,就称这两个URL同源。...
  • 同源策略和跨域

    2022-04-21 16:53:17
    MDN官方给定的概念:同源策略限制了从同一个源加载的文档或脚本如何与另一个源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。 通俗理解: A网站的JavaScript不允许与非同源的网站C之间,进行资源的交互,...
  • 下来就以 "http://www.example.com/page.html" 这个链接来比较说明:二、同源策略浏览器的同源策略是一种安全功能,同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离...
  • 7.浏览器原理之浏览器同源策略

    千次阅读 2022-02-22 18:54:40
    什么是同源策略2.如何解决跨域问题3.正向代理和反向代理的区别4.NginX的概念及其工作原理 1.什么是同源策略 2.如何解决跨域问题 3.正向代理和反向代理的区别 4.NginX的概念及其工作原理 NginX是一款轻量级的Web...
  • 目录同源策略同源策略的执行说说同源策略的限制没有同源策略的危害 同源策略 之前学习跨域方式的时候介绍过同源策略,但是学习真的不能知其一而不知其意,当时只是简单的了解,昨天面试随着面试官加深的询问没有同源...
  • 浏览器的同源策略

    2022-01-08 16:56:16
    同源策略
  • 同源策略介绍

    千次阅读 2021-08-11 21:02:01
    同源策略 同源策略限制了不同源之间如何进行资源交互,是用于隔离潜在恶意文件的重要安全机制。 是否同源由URL决定,URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。 1.file...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 43,773
精华内容 17,509
关键字:

同源策略

友情链接: CRC_CCITT.zip