浏览器家族的安全反击战

1

前言

上次我说过,我们浏览器的主要工作就是把HTML,JavaScript,CSS等文件从服务器端取下来,然后解析、渲染,展示成美奂美伦的页面呈现给人类。

我们还替人类保护一个叫做Cookie的小东西,网站会把Cookie发送给浏览器让我们保存起来,等到访问同一个网站的时候,我们再把他发过去。

这个Cookie用来证明某个用户已经和服务器交互过,更重要的是证明已经登录过系统,不用再次登录了。

JavaScript这小子在我们这里承担了越来越重要的职责,从对DOM树的改动,到利用AJAX访问服务器端,他可以说是风光无限。

(详情参见上一篇文章《浏览器:一个家族的奋斗》)

可是我们都忽视了一个重要的问题:安全,这个东西差点让我们家族遭受灭顶之灾。

2

Cookie失窃

有一天,我的主人登录了"爱存不存"银行(www.icbc.com),这个银行网站给我发了一个Cookie,证明主人登录过了, 主人在“爱存不存”银行网站做了一些操作,但是忘记了退出,然后开了一个新的Tab页访问了一个叫做www.beauty.com ,我知道这个网站不怀好意,拼命地提醒主人,但是他仍然经不住网站上那些图片的诱惑,执意把这个网站打开。

我没有办法,只好下载这个不怀好意网站的HTML,JavaScript,CSS, 让我没有想到的是这里的JavaScript竟然想访问“爱存不存”银行的Cookie。

“这个Cookie是爱存不存银行给我的,不属于www.beauty.com,你为啥要访问?” 我问他。

“没事,我好奇,想看看别的网站的Cookie长什么样”  他轻松地回答。

我将信将疑地把Cookie给了他,他不知道做了什么花样,似乎是往www.beauty.com发了一个请求,然后就把Cookie还给了我。

很快我的主人就发现,他在“爱存不存”银行的私房钱不翼而飞了。

FireFox嘲笑我说:“你这个家伙啊,怎么能够把Cookie这么重要的东西随随便便地给别人呢? ‘爱存不存’银行的Cookie被黑客偷走了,那些黑客不用登录就可以冒充用户在‘爱存不存’网站做操作了。”

“啊? 有这么严重? 可他是JavaScript,照理说可以访问啊?”

“唉,你要知道,这个JavaScript和那个Cookie不是同一个网站的,怎么能访问呢。”

由于这件事,主人再我不理我了,从此开始宠幸FireFox。

3

密码失窃

FireFox也没得意很久,他也很快中了招。

这一次,主人还是忍不住去www.beauty.com看图片,FireFox这次很小心,不把任何别的网站的Cookie发给这里的JavaScript。

但这一次beauty.com改变了策略,它用iframe的方式放置了一个淘宝的登录网页到beauty.com页面中,淘宝恰恰是主人最喜欢的,主人一看,不错啊,还有快捷登录方式,于是主人就输入了自己真实的用户名和密码,没想到Beauty.com的JavaScript 已经把这个淘宝登录Form的action指向了自家网站,等到主人点了登录按钮以后, 用户名和明文的密码就这样被窃取了。

于是FireFox也被打入冷宫。

0?wx_fmt=png

4

家族会议

黑客猖獗,类似的安全事故不断出现,我们家族的成员纷纷中招,家族赶紧召集会议,商量对策,防止人类把我们家族给废掉。

我和FireFox在会议上声讨现在的人类实在是喜欢访问那些不良网站,族长Mozilla说没办法这是人类的本性,无论如何也无法改变,如果改了就不是人类了。

“虽然我们控制不了人类的行为,但是我们浏览器家族可以做点改变,增加安全性!” Mozilla族长充满正义感和使命感,他下达了一个命令:“以后我们家族确定一条铁规:除非两个网页是来自于统一‘源头’, 否则不允许一个网页的JavaScript访问另外一个网页的内容,像Cookie,DOM,LocalStorage统统禁止访问!” 

我仔细咂摸这句话的含义,其实是说各个网页如果不同源的,就被隔离了,只能在自己的一亩三分地中折腾。

“什么叫同一个源头?” FireFox问道。

“就是说{protocol,host,port} 这三个东西必须得一样! 我给你们举个例子, 例如有这么一个网页: http://www.store.com/product/page.html, 下面的表格列出了各种不同情况。”

0?wx_fmt=png

这个同源策略确实严格, 不同源的网页无法访问另外一个网页的DOM,Cookie, 像beauty.com那样的恶意网站想偷走Cookie/密码就不容易了。

我想到了主人之前购物经常访问的http://www.store.com/, 这个页面中有一段装载jquery.js的代码:

<script src="//static.store.com/jquery.js > </script>

这个jquery.js是来自于不同的源(static.store.com), 难道他就没法操作www.store.com页面的内容了吗? 如果不能操作,这个jquery.js就没有任何用处啦!

我把这个困惑给大家说了下, FireFox马上附和: “没错,难道我们要强制人类把所有的JavaScript代码放到www.store.com下吗? 人类肯定不能容忍! ”

“嗯,这是个好问题”  Mozilla族长说,“这样,我给你们开个口子,对于使用<script src='xxxxx'> 加载的JavaScript,我们认为它的源属于www.store.com, 而不属于static.store.com,这样就可以操作www.store.com的页面了,行不行?”

我和FireFox都表示赞同,其实这种“嵌入式”的跨域加载资源的方式还有<img>,<link>等,相当于我们浏览器发起了一次GET请求,取到相关资源,然后放到本地而已。

同源策略就这么确定下来了, 我们这些浏览器都开始严格遵守执行,果然,安全事故大大减少。

5

凡事都有例外

过了一段时间,JavaScript这小子便跑来抱怨了:“你们这个同源策略实在太严格了,太不方便了。”

我说:“这也是为了大家好啊,省得那些不良网站干坏事。”

JavaScript说:“好什么好? 现在人类的系统越来越大,大部分都拆分成分布式的了,每个系统都有子域名,像login.store.com, payment.store.com, 虽然二级域名不同,但是他们属于一个大的系统,由于同源策略的铁规,cookie不能在这个系统之间共享,麻烦死了。”

这确实是个问题,我带着JavaScript找到到Mozilla组长,说明情况,希望他网开一面。

族长说:“好吧,我再给你们开个口子,如果两个网页的一级域名是相同的,他们可以共享cookie, 不过cookie的domain一定要设置为那个一级域名才可以,例如:”

document.cookie = 'test=true;path=/;domain=store.com'

JavaScript说:“还有个大问题,你们为什么不让我使用XMLHttpRequest访问不同的网站啊!”

我心想JavaScript说的可能是AJAX,可以创建一个XMLHttpRequest对象去异步的访问服务器端提供的服务,做到局部刷新页面,用户体验很好。

难道这个XMLHttpRequest对象只能访问源服务器(如book.com),不能访问其他服务器(如beauty.com)?

0?wx_fmt=gif

0?wx_fmt=png

族长说:“是啊,XMLHttpReqeust也要遵守同源策略。”

JavaScript说:“可是这没有道理啊!我虽然是从book.com来的,但是为什么不让我访问beauty.com?”

族长说:“我这也是为了防止黑客攻击,给你举个例子,假设你的主人登录了book.com , 然后又去访问beauty.com,如果这个beauty.com是个恶意网站,它也要求你创建一个XMLHttpRequest对象,通过这个对象向book.com(不同源)发起请求,获取你主人的账户信息,会发生什么情况? ”

JavaScript恍然大悟:“奥,我懂了,由于主人登录过了book.com,登录cookie什么的都在,那beauty.com的JavaScript 向book.com发起的XMLHttpRequest请求也会成功,我主人的账户信息就会被黑客给获取了。”

我说:“看来对XMLHttpReqeust对象施加同源策略也是非常重要的啊!”

JavaScript沉默了半天说:“那怎么办?”

Mozilla族长说:“你可以通过服务器端中转啊,例如你是来自book.com的, 现在想访问movie.com,那可以让那个book.com把请求转发给movie.com嘛!人类好像给这种方式起了个名字,叫什么代理模式,那个book.com就是代理人。”

0?wx_fmt=gif

0?wx_fmt=png

JavaScript急忙说:“不不, 这样太麻烦了,族长你想想,如果我要访问多个不同源的系统,要是都通过book.com中转,该多麻烦!”

族长想了想说:“你说得有一定道理,我给你出个主意,既然服务器(domain)之间是互信的,那一个服务器(domain)可以设置一个白名单,里边列出它允许哪些服务器(domain)的AJAX请求。假设movie.com的白名单中有book.com, 那当属于book.com的JavaScript试图访问movie.com的时候......”

JavaScript马上接口说:“ 这时候,我们浏览器做点手脚,悄悄地把当前的源(book.com)发过去,询问下movie.com, 看看他是否允许我们访问,如何允许,你们就继续访问,否则就报错!”

0?wx_fmt=gif

0?wx_fmt=png

组长说:“就是这个意思,这样以来,那些黑客就没有办法假冒用户向这些互信的服务器发送请求了, 我把这个方法叫做Cross Origin Resource Sharing,简称CORS,只不过这个方法需要服务器的配合了”

(码农翻身注:上面说的是CORS的简单请求,对于Preflight请求,本文不在展开描述)

JavaScript表示同意,这也算是一个不错的妥协方法了。

(完)

你看到的只是冰山一角, 更多精彩文章,请移步《2016文章精华》或者《2017上半年文章精华


码农翻身

用故事讲述技术

0.jpeg

内容概要:本文围绕列车-轨道-桥梁交互仿真研究,基于Matlab平台构建数值模型,系统分析列车运行过程中轨道与桥梁结构间的动态相互作用机制。研究涵盖多体动力学建模、耦合系统运动方程求解、边界条件设定及仿真结果可视化等关键环节,重点揭示高速行车条件下基础设施的振动传递规律与力学响应特征。该仿真方法可有效评估结构安全性、舒适性指标及疲劳寿命,为轨道交通工程的设计优化与运维管理提供理论支撑和技术路径。文中配套提供了完整的Matlab代码实现方案及操作说明,便于用户复现、验证和拓展相关研究。; 适合人群:具备Matlab编程基础和结构动力学、车辆动力学等相关专业知识的研究生、科研人员及从事铁路工程、桥梁工程与交通系统安全评估的工程技术人才,尤其适合开展轨道交通耦合振动课题的研究者。; 使用场景及目标:①用于高校与科研机构进行列车-轨道-桥梁耦合系统动力学特性的教学演示与科学研究;②支撑高速铁路桥梁的设计优化、运营安全性评估与减振降噪方案验证;③为复杂交通基础设施的多物理场耦合仿真提供建模思路与代码参考。; 阅读建议:建议读者结合所提供的Matlab代码逐模块深入研读,重点关注系统建模假设、质量-刚度-阻尼矩阵构建方法及数值积分算法的实现细节,同时可通过调整参数进行敏感性分析,进一步掌握仿真模型的适用范围与优化方向。
内容概要:本文系统研究了非线性薛定谔方程的物理信息神经网络(PINN)求解方法,提出一种将物理规律嵌入深度学习模型的科学计算新范式。通过构建全连接神经网络架构,将非线性薛定谔方程及其初始/边界条件作为损失函数的核心组成部分,实现了在无须大量标注数据的前提下对复值偏微分方程的高精度数值求解。该方法充分利用自动微分技术精确计算方程残差,有效融合了数据驱动与模型驱动的优势,在光学孤子传播、量子系统演化等典型场景中展现出优异的逼近能力与泛化性能。文中配套提供了完整的Python实现代码,涵盖网络搭建、损失定义、训练优化与结果可视化全流程。; 适合人群:具备Python编程能力与深度学习基础知识,熟悉偏微分方程理论及科学计算的理工科研究生、科研人员,以及从事光学、量子物理、流体力学等领域建模与仿真的工程技术人员。; 使用场景及目标:① 掌握PINN方法的基本原理与实现技巧;② 学习如何将复杂物理方程转化为可训练的神经网络损失项;③ 应用于非线性光学、玻色-爱因斯坦凝聚、水波动力学等问题的仿真与预测;④ 为相关科研课题提供可复现的算法原型与代码参考。; 阅读建议:建议读者结合所提供的Python代码进行动手实践,重点理解神经网络对微分算子的近似机制、损失函数的多任务加权策略以及训练过程中的超参数调优方法,进而可迁移至其他非线性偏微分方程的求解任务,拓展其在交叉学科中的应用边界。
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 微软推出的【AZ-900微软认证】是一项针对初学者的基础级云服务资格认证,其目的在于帮助学习者掌握云概念、微软Azure服务的运作机制以及云解决方案的核心知识。获得这一认证后,考生将能够清晰地理解云计算领域的基础术语、服务模式(包括IaaS、PaaS、SaaS等)以及这些服务在Azure平台上的实际应用方式。 在【必过考题】部分,我们可以观察到两个重点议题,它们分别聚焦于PaaS(平台即服务)的概念阐释和云成本的计算方式。 在第一个议题中,考生被要求辨别关于PaaS的正确性描述。PaaS平台提供了一个开发环境,但并不允许用户直接访问操作系统(Box 1: No)。比如,Azure Web Apps服务可以用来部署web应用,但用户无法直接管理虚拟机或IIS系统。另一方面,PaaS确实具备自动扩展的功能(Box 2: Yes),这表示可以根据实际需求自动增加负载均衡的虚拟机以支持web应用的运行。PaaS框架还为开发人员提供了构建和调整云端应用的工具,预置的应用组件能够有效缩短新应用的编程周期(Box 3: Yes)。 第二个议题同样关注云计算理念的理解,尤其强调IT支出从资本性支出(CapEx)向运营性支出(OpEx)的转型思想。传统的IT投资通常被视为CapEx,而云计算的按需付费机制使企业能够将这部分开支转化为OpEx,从而在财务规划上获得更大的自由度。 在为AZ-900考试做准备时,考生需要特别关注以下几个核心知识点: 1. **云服务模式**:深入理解IaaS(基础设施即服务)、PaaS和SaaS(软件即服务)之间的差异及其各自的应用情境。 2. **Azure服务*...
源码下载地址: https://pan.quark.cn/s/239a0d536a1e 依据所提供的文件资料,可以归纳出以下核心内容:由清华大学计算机系邓俊辉教授精心编纂的算法训练营题目合集,对于CSP(中国软件专业人才设计与创业大赛)及PAT(程序设计能力测试)这类编程竞赛具有极高的参考价值,堪称一份极具价值的参考资料。此类竞赛普遍对参赛者的算法功底和编程技巧提出严苛要求。该合集中的题目与算法领域紧密相连,其中包含了“最大红矩形”这一典型题目。所谓最大红矩形题目,其核心任务是针对一个由红色与绿色方格构成的棋盘,寻觅出最大的纯红矩形区域。要攻克这一问题,必须运用数据结构与算法的相关知识,特别是栈这一数据结构的应用。 “最大红矩形”问题能够被抽象转化为“直方图最大面积”问题。具体转化方法是将棋盘的每一列视为一个独立的直方图单元,其中红色方格的贡献体现为当前位置与前一个绿色方格所在行数的差值,从而保证每个直方图的基宽恒定为1。随后,借助扫描直方图的技术手段来探寻最大矩形面积。这一过程需要对每个直方图进行系统性遍历,并利用栈来记录各直方图的下标信息。一旦检测到当前直方图的高度小于栈顶元素所记录的高度,则意味着遭遇了一个“高点”,此时需计算以该“高点”为右边界条件的最大矩形面积。 在编程实践环节,必须高度关注栈的操作细节,以及如何精确地初始化和操纵栈来应对直方图问题。代码实现中,通常配置两个栈,一个用于储存直方图的高度值,另一个用于标记直方图的下标位置。当面对新高度时,需审慎判断当前高度与栈顶高度的相对关系,并据此抉择是执行入栈操作还是计算面积。针对“低点”(即当前高度小于栈顶),应直接将当前高度纳入栈中;而对于“高点”,则需执行弹出栈顶元素的操作,并基于该栈顶元素的高...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值