当前位置: 首页 > news >正文

跨域问题讨论

问题

跨域定义

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

跨域的安全隐患(CSRF攻击)

在这里插入图片描述

也就是说,一旦允许跨域,意味着允许恶意网站随意攻击可信网站,带来安全风险。

这里面有一个前提:

用户必须先登录可信站点A才行(登录cookie会保存在客户本地)。

解决方案

SOP策略

SOP:same-origin policy,同源策略

现代浏览器默认遵循同源策略,即网站A的请求不能去访问网站B。

但,<img>、<iframe>、<script>、<link>、<video>、<audio>等标签不受同源策略约束,这些标签可以通过src属性请求到其他服务器上的数据;如<img>的src(获取图片),<script>的src(获取javascript),iframe更是把不同网站的前端页面无缝衔接起来的常用技巧。

所以,即使在浏览器支持SOP的情况下,前例中的恶意网站仍可以构造例如img src这样的恶意代码,绕过浏览器的SOP规则,访问正常网站A。

不受SOP限制的资源清单:
脚本文件 js
图片资源
样式资源css
iframe展示其他的的资源
a链接访问其他资源
多媒体等资源
form表单提交

受SOP限制的资源清单:
跨域的XHR请求
iframe可以访问iframe整体,不能访问内容
cookie的限制,使用CORS需要withCredentials=true才可以带上cookie,否则cookie都没法带。

CORS机制

SOP原则可防范跨域,但如果确有需要跨域,如何安全的进行呢?

W3C推荐了一种跨域的访问验证的机制,即CORS(Cross-Origin Resource Sharing 跨源资源共享)。

这种机制让Web应用服务器能支持跨域访问,减轻跨域请求的风险。 CORS验证机制需要客户端和服务端协同处理。

CORS原理具体可参考这里。

写得非常详细,我们可以概况为:为支持CORS,浏览器为我们的跨站XHR请求自动加了一个额外的请求头Origin,记录原始站点O,询问后台是否允许跨域(复杂请求会先自动通过OPTIONS请求专门询问一次,简单请求就没有提前的OPTIONS询问了),后台在响应头里返回关键字段Access-Control-Allow-Origin,给出允许跨域的网址P。浏览器将P跟O匹配,匹配上了,就可以继续访问,匹配不上就报错。若响应头里没有Access-Control-Allow-Origin字段,说明后台就不接受跨域XHR请求,浏览器会报:

No 'Access-Control-Allow-Origin' header is present on the requested resource

观察下来,对于简单请求(例如GET),实际运行中,浏览器其实是调了后台服务的,只不过后台服务没返回Access-Control-Allow-Origin,浏览器直接把结果扔了,对调用者报了这个错。对于POST请求,因为我们一般都是传的json,算复杂请求,会自动触发OPTIONS询问,就不会真正调用到后台服务的业务处理里了。

顺带说一下,域内请求,就没有Origin字段了,后台去拿,也只能拿到null或空。另外,因为CORS安全约束,请求头里的Origin字段是浏览器自动设置的,程序是无法强改的(能改的话,CORS机制就形同虚设了)。

由于浏览器侧是自动处理的,我们主要看后台的代码处理,以flask为例 :

@app.route('/repair_plans/page/<int:page_size>/<int:cur_page>')
def query_data(page_size, cur_page):app.logger.info('size:%d, cur_page:%d' % (page_size, cur_page))res =  jsonify(pageVO = {'totalRows':1},result = [])res.headers['Access-Control-Allow-Origin'] = request.headers.get('Origin')res.headers['Access-Control-Allow-Methods'] = 'GET'res.headers['Access-Control-Allow-Headers'] = 'x-requested-with,content-type'return res

逻辑很简单,把Access-Control-Allow-Origin等几个CORS相关的响应头补上去即可。这里说明一下,Access-Control-Allow-Origin可以指定是原始站点O,也可以是一个预置的合法站点,一般不建议用星号通配符。若该字段设置为None或空,前端的跨域XHR请求就会报错:

The 'Access-Control-Allow-Origin' header contains the invalid value 'None'.

csrf token

准确的讲,CORS是跨域访问的例外规范,而非跨域攻击的防范。

跨域攻击的防范,首先还是浏览器的SOP策略,但前面说了,SOP有例外,像img src、链接、表单提交等都可以绕过SOP,浏览器不会报错,且这些做法的请求头里都没有Origin字段,后台只能通过检查referer字段来防范。但referer字段是可以在浏览器里配置不发送的(出于隐私保护的考虑)。最后,即便浏览器支持,你也不知道这个浏览器是否因安全漏洞被攻陷,导致referer可被篡改,所以还需要一个更强的防范措施,这就是csrf token。

用户登录后,随机生成csrf_token,用户在做核心操作表单提交(POST)时必须在请求头里携带csrf_token,并且在服务端校验csrf_token的合法性。由于恶意站点是无法构造CSRF Token的(只有登陆可信站点才能获取到,且CSRF Token一般不放在cookie中),因此CSRF Token是目前最成熟、使用最广泛的方法。
这是SO上的一段说明,印证了本节的说法:

Origin vs Referer vs CSRF token
Most likely, the reason OWASP recommends also using a CSRF token, is that at the time when this recommendation was made - a significant portion of browsers did not yet support the Origin header. This is no longer the case, but people are chimpanzees.In order to preserve privacy, any browser request can decide to omit the Referer header. So it is probably best to only check the Origin header. (In case you want to allow for users to preserve their privacy)The Origin header is null in some cases. Note that all of these requests are GET requests, which means they should not have any side effects.As long as you make sure the malicious website sending the requests with your browser cannot read the responses, you should be fine. This can be ensured using proper CORS headers. (Do not use Access-Control-Allow-Origin: *!)To prevent "click-jacking", set the header X-Frame-Options: DENY. This will tell your browser that it is not allowed to display any part of your website in an iframe.

大意是说,referer、Origin不是万无一失的,最好补充上csrf token。

反向代理

参见这里。

这里把对网站A和B的访问都集中到nginx处,天然回避了跨域(比如,A访问B)的问题。

http://www.lryc.cn/news/178672.html

相关文章:

  • ESP32设备通信-两个ESP32设备之间HTTP通信
  • 数据结构学习笔记——查找算法中的树形查找(平衡二叉树)
  • P1830 轰炸III
  • 大语言模型LLM知多少?
  • Redis命令行使用Lua脚本
  • HTML详细基础(三)表单控件
  • map和set的具体用法 【C++】
  • 聚合统一,SpringBoot实现全局响应和全局异常处理
  • 【C/C++笔试练习】——数组名和数组名、switch循环语句、数据在计算机中的存储顺序、字符串中找出连续最长的数字串、数组中出现次数超过一半的数字
  • 力扣每日一题(+日常水题|树型dp)
  • 使用perming加速训练可预测的模型
  • 【数据库】存储引擎InnoDB、MyISAM、关系型数据库和非关系型数据库、如何执行一条SQL等重点知识汇总
  • 车道线分割检测
  • 树莓集团又一力作,打造天府蜂巢成都直播产业园样板工程
  • ubuntu 软件包管理之二制作升级包
  • TCP/IP网络江湖——数据链路层的防御招式(数据链路层下篇:数据链路层的安全问题)
  • ios项目安装hermes-engine太慢问题
  • 构建个人云存储:本地电脑搭建SFTP服务器,开启公网访问,轻松共享与管理个人文件!
  • springboot 下载文件为excel数据,中文自定义单元格宽度
  • 机器学习 面试/笔试题
  • 某企查ymg_ssr列表详情
  • 使用YOLOv5的backbone网络识别图像天气 - P9
  • TikTok海外扩张:亚马逊的新对手崛起
  • CSS详细基础(五)选择器的优先级
  • LLM-TAP随笔——有监督微调【深度学习】【PyTorch】【LLM】
  • kafka伪集群部署,使用docker环境拷贝模式
  • 工业交换机一般的价格是多少呢?
  • QT使用前的知识
  • Unity制作旋转光束
  • 考研王道强化阶段(二轮复习)“算法题”备考打卡表 记录