# 前端安全

几种前端安全相关的

1. XSS，Cross Site Script，跨站脚本攻击。

原理是攻击者通过某种方式在网页上嵌入脚本代码，这样，正当用户在浏览网页或执行操作的时候，脚本被执行，就会触发攻击者预期的“不正当”行为。举个例子。在 \[第 29 讲] 中我介绍了会话的原理，服务端给用户分配了一个标识身份的字符串，整个会话生命周期内有效，保存在浏览器的 Cookie 中（如果你忘记了，请回看）。

知道了原理，我们就可以针对 XSS 的特点来进行防御，比如有这样两个思路： 第一个，做好字符转义和过滤，让用户上传的文本在展示的时候永远只是文本，而不可能变成 HTML 和脚本。 第二个，控制好 Cookie 的作用范围。比如服务器在返回 Set-Cookie 头的时候，设置 HttpOnly 这个标识，这样浏览器

当然上述内容只是 XSS 原理的一个简单示意，实际的跨站脚本攻击会比这个复杂且隐蔽得多。而且，这个跨站脚本可不只是能偷偷摸摸地把用户的 Cookie 传给攻击者，还能做其它的事情，比如我下面将要介绍的 CSRF。

2. CSRF

CSRF，Cross-Site Request Forgery，跨站请求伪造，它指的是攻击者让用户进行非其本意的操作。CSRF 和 XSS 的最大区别在于，在 CSRF 的情况下，用户的“非其本意”的行为全部都是从受害用户的浏览器上发生的，而不是从攻击者的浏览器上挟持用户会话以后发起的。

针对 CSRF 的策略 第一种，使用 HTTP 的 Referer 头，因为 Referer 头可以携带请求的来源页面地址，这样可以根据 Referer 头鉴别出伪造的请求。 第二种，使用 token，原理上也很简单，服务端给每个表单都生成一个随机值，这个值叫做 token。Token 和我们前面讲到的用来标识用户身份的 Cookie 所不同的是，前者是对每个页面或每个表单就会生成一个新的值，而后者则是只有会话重新生成的时候才会生成。当用户正常操作的时候，这个 token 会被带上，从而证明用户操作的合法性，而如果是 CSRF 的情形，这个请求来自于一个非预期的位置，那么就不可能带有这个正确的 token。

值得注意的是，CSRF 和 XSS 不是地位均等的，具体说，在防范 CSRF 的情况下，必须首先确保没有 XSS 的问题，否则 CSRF 就会失去意义。

因为一旦用户的会话以 XSS 的方式被劫持，攻击者就可以在他自己的浏览器中假装被劫持用户而进行操作。由于攻击者在他自己的浏览器中遵循着正确的操作流程，因而这种情况下无论是 Referer 头还是 token，从服务端的角度来看都是没有问题的，也就是说，当 XSS 被攻破，所有的 CSRF 的防御就失去了意义。

3. SQL 注入

SQL 注入，指的是攻击者利用网站漏洞，通过构造特殊的嵌入了 SQL 命令的网站请求以欺骗服务器，并执行该恶意 SQL 命令。

知道了原理，那么我们就可以采取相应的措施来应对了： 第一种，对于参数进行转义和过滤，这和我们前面介绍的 XSS 的应对是一样的。如果参数的格式明确，我们应当较为严格地校验参数，比如上面的例子，如果 id 实际是一个数值，那么用户输入非数值就应当报错。 第二种，SQL 的语句执行尽可能采用参数化查询的接口，而不是单纯地当做字符串来拼接。当然，一般在使用持久化框架的时候，这样的事情框架一般都替程序员考虑到了。 第三种，严格的权限控制，这和 Linux 下面权限控制的原则是一样的，保持“最小授权”原则，即尽可能只授予能实现功能的最小权限。

4. HTTP 劫持

HTTP 劫持的原理很简单，但是却非常常见。就是说，由于 HTTP 协议是明文通信的，它就可以被任意篡改。而干这事儿干得最多的，不是什么传统意义上的“黑客”，而是那些无良的网络服务提供商和运营商们，他们利用对网络控制之便利，通过这种方式强行给用户塞广告。

对于 HTTP 劫持，由于攻击者利用了 HTTP 明文传输的特性，因此解决方案很简单，就是将网站切换为 HTTPS。至于其它的方法，相对都比较特例化，并不一般和通用，只有将传输加密才是最理想的解决方案。

5. DNS 劫持

用户的浏览器在通过 DNS 查询目标域名对应的 IP 地址的时候，会被攻击者引导到一个恶意网站的地址。这个假的网站也可以有相似的页面布局，也可能有“正规”方式申请的 HTTPS 证书，换言之，HTTPS 加密通信并不能防范 DNS 劫持，因此用户很可能被欺骗而不察觉。

DNS 假如被劫持了，浏览器都去和一个假冒的网站通信了，HTTPS 加密做的也只是保证你和这个假冒网站通信的完整性、保密性，那还有何用？就好比要去药店买药，可去了家假的药店，那么保证整个交易过程的安全性就失去了它原本的意义了

安全防范的各个环节就像一个木桶的各个木板，网络公共服务的安全性，经常决定了用户网上冲浪安全性的上限

事实上，安全防范的各个环节就像一个木桶的各个木板，网络公共服务的安全性，经常决定了用户网上冲浪安全性的上限。2010 年的百度被黑事件，就是遭遇了 DNS 劫持。由于 DNS 解析的过程比较长，劫持可能发生在网络，也可以发生在本机（别忘了本机有 hosts 文件），还可能发生在某一个子网的路由。对于 DNS 网络明文通信带来的隐患，有一个安全的域名解析方案，叫做 DNS over HTTPS，目前还在实验阶段，仅有部分 DNS 服务支持。

6. DDoS 攻击

最后我来简单介绍一下 DDoS，Distributed Denial-of-Service，分布式拒绝服务，这种攻击方式从理论上说，最难以防范，被称为互联网的“癌症”。

为什么呢？因为它的原理是，攻击者使用若干被“攻陷”的电脑（比如被病毒占领和控制的“肉鸡”），向网络应用和服务同一时间发起请求，通过一瞬间的请求洪峰，将服务冲垮。

DDoS 攻击的目的不是偷窃用户数据，也不是为了仿冒用户身份，而是“无差别”阻塞网络，引发“拒绝服务”，让正常使用网站和应用的用户难以继续使用，这个“无差别”最要命，简单、粗暴，但却有效。

因此对于 DDoS 的攻击，我们需要整个网络链路配合，包括路由器、交换机、防火墙等等组件，采取入侵检测和流量过滤等多种方式来联合防范。这部分的内容涉及比较多，我在扩展阅读放了一点材料，感兴趣的话可以阅读。

XSS 和 CSRF 都和身份有关系，前者是劫持了某个身份，后者是假冒了某个身份

## 什么是 CSRF 攻击

CSRF（Cross-site request forgery 跨站请求伪造，也被称为“One Click Attack”或者 Session Riding，通常缩写为 CSRF 或者 XSRF，是一种对网站的恶意利用。尽管听起来像跨站脚本（XSS），但它与 XSS 非常不同，并且攻击方式几乎相左。XSS 利用站点内的信任用户，而 CSRF 则通过伪装来自受信任用户的请求来利用受信任的网站。与 XSS 攻击相比，CSRF 攻击往往不大流行（因此对其进行防范的资源也相当稀少）和难以防范，所以被认为比 XSS 更具危险性。

为什么会出现 CSRF 攻击？举例说明比如说有两个网站 A 和 B。你是 A 网站的管理员，你在 A 网站有一个权限是删除用户，比如说这个过程只需用你的身份登陆并且 POST 数据到 【http://a.com/delUser 】， 就可以实现删除操作。好现在说 B 网站，B 网站被攻击了，别人种下了恶意代码，你点开的时候就会模拟跨域请求，如果是针对你，那么就可以模拟对 A 站的跨域请求，恰好这个时候你已经在 A 站登陆了。那么攻击者 在 B 站内通过脚本，模拟一个用户删除操作是很简单的。面对这种问题，有从浏览器解决，但个人认为最好是从网站端解决，检测每次 POST 过来数据时的 Refer，添加 AccessToken 等都是好方法。

一个典型的 CSRF 攻击有着如下的流程：

受害者登录 a.com，并保留了登录凭证（Cookie）。 攻击者引诱受害者访问了 b.com。 b.com 向 a.com 发送了一个请求：a.com/act=xx。浏览器会默认携带 a.com 的 Cookie。 a.com 接收到请求后，对请求进行验证，并确认是受害者的凭证，误以为是受害者自己发送的请求。 a.com 以受害者的名义执行了 act=xx。 攻击完成，攻击者在受害者不知情的情况下，冒充受害者，让 a.com 执行了自己定义的操作。

常见的攻击类型

* GET 类型的 CSRF
* POST 类型的 CSRF
* 链接类型的 CSRF

防范 CSRF 攻击可以遵循以下几种规则：

1. Get 请求不对数据进行修改
2. 不让第三方网站访问到用户 Cookie
3. 阻止第三方网站请求接口 referer
4. 请求时附带验证信息，比如验证码或者 Token

上文中讲了 CSRF 的两个特点：

* CSRF（通常）发生在第三方域名。
* CSRF 攻击者不能获取到 Cookie 等信息，只是使用。

针对这两点，我们可以专门制定防护策略，如下：

阻止不明外域的访问 同源检测 Samesite Cookie 提交时要求附加本域才能获取的信息 CSRF Token 双重 Cookie 验证 以下我们对各种防护方法做详细说明

在 HTTP 协议中，每一个异步请求都会携带两个 Header，用于标记来源域名：

Origin Header Referer Header 这两个 Header 在浏览器发起请求时，大多数情况会自动带上，并且不能由前端自定义内容。 服务器可以通过解析这两个 Header 中的域名，确定请求的来源域。

使用 Origin Header 确定来源域名 在部分与 CSRF 有关的请求中，请求的 Header 中会携带 Origin 字段。字段内包含请求的域名（不包含 path 及 query）。

如果 Origin 存在，那么直接使用 Origin 中的字段确认来源域名就可以。

设置 Referrer-Policy 的方法有三种：

* 在 CSP 设置
* 页面头部增加 meta 标签
* a 标签增加 referrer-policy 属性

令牌同步模式 令牌同步模式（英語：Synchronizer token pattern，简称 STP）。原理是：当用户发送请求时，服务器端应用将令牌（英語：token，一个保密且唯一的值）嵌入 HTML 表格，并发送给客户端。客户端提交 HTML 表格时候，会将令牌发送到服务端，令牌的验证是由服务端实行的。令牌可以通过任何方式生成，只要确保随机性和唯一性（如：使用随机种子【英語：random seed】的哈希链 ）。这样确保攻击者发送请求时候，由于没有该令牌而无法通过验证。

檢查 Referer 字段 HTTP 頭中有一個 Referer 字段，這個字段用以標明請求來源於哪個地址。在處理敏感數據請求時，通常來說，Referer 字段應和請求的地址位於同一域名下。以上文銀行操作為例，Referer 字段地址通常應該是轉帳按鈕所在的網頁地址，應該也位於 bank.example.com 之下。而如果是 CSRF 攻擊傳來的請求，Referer 字段會是包含惡意網址的地址，不會位於 bank.example.com 之下，這時候伺服器就能識別出惡意的訪問。

這種辦法簡單易行，工作量低，僅需要在關鍵訪問處增加一步校驗。但這種辦法也有其局限性，因其完全依賴瀏覽器發送正確的 Referer 字段。雖然 http 協議對此字段的內容有明確的規定，但並無法保證來訪的瀏覽器的具體實現，亦無法保證瀏覽器沒有安全漏洞影響到此字段。并且也存在攻擊者攻擊某些瀏覽器，篡改其 Referer 字段的可能。

添加校驗 token 由於 CSRF 的本質在於攻擊者欺騙用戶去訪問自己設置的地址，所以如果要求在訪問敏感數據請求時，要求用戶瀏覽器提供不保存在 cookie 中，并且攻擊者無法偽造的數據作為校驗，那麼攻擊者就無法再執行 CSRF 攻擊。這種數據通常是表單中的一個數據項。伺服器將其生成並附加在表單中，其內容是一個偽亂數。當客戶端通過表單提交請求時，這個偽亂數也一並提交上去以供校驗。正常的訪問時，客戶端瀏覽器能夠正確得到並傳回這個偽亂數，而通過 CSRF 傳來的欺騙性攻擊中，攻擊者無從事先得知這個偽亂數的值，伺服器端就會因為校驗 token 的值為空或者錯誤，拒絕這個可疑請求。

在使用 .innerHTML、.outerHTML、document.write() 时要特别小心，不要把不可信的数据作为 HTML 插到页面上，而应尽量使用 .textContent、.setAttribute() 等。

CSP 是为了解决 XSS 攻击

Content Security Policy 严格的 CSP 在 XSS 的防范中可以起到以下的作用：

禁止加载外域代码，防止复杂的攻击逻辑。 禁止外域提交，网站被攻击后，用户的数据不会泄露到外域。 禁止内联脚本执行（规则较严格，目前发现 GitHub 使用）。 禁止未授权的脚本执行（新特性，Google Map 移动版在使用）。 合理使用上报可以及时发现 XSS，利于尽快修复问题。

输入内容长度控制 对于不受信任的输入，都应该限定一个合理的长度。虽然无法完全防止 XSS 发生，但可以增加 XSS 攻击的难度。

其他安全措施 HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie，攻击者完成 XSS 注入后也无法窃取此 Cookie。 验证码：防止脚本冒充用户提交危险操作。

做了 HTML 转义，并不等于高枕无忧。 对于链接跳转，如 \<a href="xxx" 或 location.href="xxx"，要检验其内容，禁止以 javascript: 开头的链接，和其他非法的 scheme。

Samesite Cookie 属性

Samesite=Strict 这种称为严格模式，表明这个 Cookie 在任何情况下都不可能作为第三方 Cookie，绝无例外。

Samesite=Lax 这种称为宽松模式，比 Strict 放宽了点限制：假如这个请求是这种请求（改变了当前页面或者打开了新页面）且同时是个 GET 请求，则这个 Cookie 可以作为第三方 Cookie。比如说 b.com 设置了如下 Cookie：

我们应该如何使用 SamesiteCookie 如果 SamesiteCookie 被设置为 Strict，浏览器在任何跨域请求中都不会携带 Cookie，新标签重新打开也不携带，所以说 CSRF 攻击基本没有机会。

但是跳转子域名或者是新标签重新打开刚登陆的网站，之前的 Cookie 都不会存在。尤其是有登录的网站，那么我们新打开一个标签进入，或者跳转到子域名的网站，都需要重新登录。对于用户来讲，可能体验不会很好。

如果 SamesiteCookie 被设置为 Lax，那么其他网站通过页面跳转过来的时候可以使用 Cookie，可以保障外域连接打开页面时用户的登录状态。但相应的，其安全性也比较低。

另外一个问题是 Samesite 的兼容性不是很好，现阶段除了从新版 Chrome 和 Firefox 支持以外，Safari 以及 iOS Safari 都还不支持，现阶段看来暂时还不能普及。

而且，SamesiteCookie 目前有一个致命的缺陷：不支持子域。例如，种在 topic.a.com 下的 Cookie，并不能使用 a.com 下种植的 SamesiteCookie。这就导致了当我们网站有多个子域名时，不能使用 SamesiteCookie 在主域名存储用户登录信息。每个子域名都需要用户重新登录一次。

总结 简单总结一下上文的防护策略：

CSRF 自动防御策略：同源检测（Origin 和 Referer 验证）。 CSRF 主动防御措施：Token 验证 或者 双重 Cookie 验证 以及配合 Samesite Cookie。 保证页面的幂等性，后端接口不要在 GET 页面中做用户操作。

## 什么是 XSS 攻击

Cross-Site Scripting（跨站脚本攻击）简称 XSS，是一种代码注入攻击。XSS 可以分为多种类型，但是总体上我认为分为两类：持久型、非持久型和 DOM-Based 型 XSS.

XSS 的本质是：恶意代码未经过滤，与网站正常的代码混在一起；浏览器无法分辨哪些脚本是可信的，导致恶意脚本被执行。

而由于直接在用户的终端执行，恶意代码能够直接获取用户的信息，或者利用这些信息冒充用户向网站发起攻击者定义的请求。

在部分情况下，由于输入的限制，注入的恶意脚本比较短。但可以通过引入外部的脚本，并由浏览器执行，来完成比较复杂的攻击策略。

这里有一个问题：用户是通过哪种方法“注入”恶意脚本的呢？

不仅仅是业务上的“用户的 UGC 内容”可以进行注入，包括 URL 上的参数等都可以是攻击的来源。在处理输入时，以下内容都不可信：

* 来自用户的 UGC 信息
* 来自第三方的链接
* URL 参数
* POST 参数
* Referer （可能来自不可信的来源）
* Cookie （可能来自其他子域注入）

XSS 分类

存储型、反射型和 DOM 型三种。

* 持久型也就是攻击的代码被服务端写入进数据库中，这种攻击危害性很大，因为如果网站访问量很大的话，就会导致大量正常访问页面的用户都受到攻击。
* 一次性（非持久性）
* 通过用户点击链接引起
* 反射型 XSS，也可称为非持久型 XSS。
* 其攻击方式往往是通过诱导用户去点击一些带有恶意脚本参数的 URL 而发起的。
* 事实上由于反射型 XSS 因为 URL 特征导致很容易被防御。很多浏览器如 Chrome 都内置了 相应的 XSS 过滤器，来防范用户点击了反射型 XSS 的恶意链接
* 反射型 XSS 归根到底就是由于不可信的用户输入被服务器在没有安全防范处理，然后就直接使用到响应页面中，然后反射给用户而导致代码在浏览器执行的一种 XSS 漏洞。
* DOM 型 XSS
* DOM 型 XSS 的攻击步骤：
* 攻击者构造出特殊的 URL，其中包含恶意代码。
* 用户打开带有恶意代码的 URL。
* 用户浏览器接收到响应后解析执行，前端 JavaScript 取出 URL 中的恶意代码并执行。
* 恶意代码窃取用户数据并发送到攻击者的网站，或者冒充用户的行为，调用目标网站接口执行攻击者指定的操作。
* DOM 型 XSS 跟前两种 XSS 的区别：DOM 型 XSS 攻击中，取出和执行恶意代码由浏览器端完成，属于前端 JavaScript 自身的安全漏洞，而其他两种 XSS 都属于服务端的安全漏洞。

XSS 攻击的预防

XSS 攻击有两大要素：

攻击者提交恶意代码。 浏览器执行恶意代码。

XSS 主要做什么事：

* 窃取用户 Cookie
* 伪造请求
* XSS 钓鱼

防范措施： 针对 URL 编码， HTML 编码， JS 编码。 URL 只能使用英文字母（a-zA-Z）、数字（0-9）、-\_.\~4 个特殊字符以及所有（; , /?:@&=+$#）保留字符。 例如：

```js
// 使用了汉字
var url1 = 'http://www.帅.com';

然后由于 encodeURI 不转义 & 、 ? 和 = 。
    使用encodeURLComponent

// "http://a.com?a=%3F%26"
encodeURI('http://a.com') + '?a=' + encodeURIComponent('?&');
// 相应的解码
decodeURl()
decodeURLComponent()
```

判断输入格式： 过滤特殊字符：<、 > 、&、\
过滤危险字符： 去除<"script"> 、javascript、onclik

```js
/**
 * 转义 HTML 特殊字符
 * @param {String} str
 */
function htmlEncode(str) {
  return String(str)
    .replace(/&/g, "&amp;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
}

// 正则获取危险标签
var REGEXP_TAG = /<(script|style|iframe)[^<>]*?>.*?<\/\1>/gi;
// 正则获取危险标签属性
var REGEXP_ATTR_NAME = /(onerror|onclick)=([\"\']?)([^\"\'>]*?)\2/gi;

/**
 * 过滤函数
 */
function filter(str) {
  return String(str).replace(REGEXP_TAG, "").replace(REGEXP_ATTR_NAME, "");
}
```

但是输入侧过滤一旦攻击者绕过前端过滤，直接构造请求，就可以提交恶意代码了。

当然，对于明确的输入类型，例如数字、URL、电话号码、邮件地址等等内容，进行输入过滤还是必要的。

既然输入过滤并非完全可靠，我们就要通过“防止浏览器执行恶意代码”来防范 XSS。这部分分为两类： 预防存储型和反射型 XSS 攻击

防止 HTML 中出现注入。 防止 JavaScript 执行时，执行恶意代码。

预防这两种漏洞，有两种常见做法：

* 改成纯前端渲染，把代码和数据分隔开。
* 对 HTML 做充分转义。

## XSS 的防御方式

1. httpOnly 原理：浏览器禁止页面的 Javascript 访问带有 HttpOnly 属性的 cookie。（实质解决的是：XSS 后的 cookie 劫持攻击）如今已成为一种“标准”的做法

解决方案： JavaEE 给 Cookie 添加 HttpOnly 的方式为：

```js
response.setHeader(
  "Set-Cookie",
  "cookiename=value; Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly"
);
```

2. 输入检查(XSS Filter)

原理：让一些基于特殊字符的攻击失效。（常见的 Web 漏洞如 XSS、SQLInjection 等，都要求攻击者构造一些特殊字符）

* 输入检查的逻辑，必须在服务端实现，因为客户端的检查也是很容易被攻击者绕过，现有的普遍做法是两端都做同样的检查，客户端的检查可以阻挡大部分误操作的正常用户，从而节约服务器的资源。

解决方案： 检查是否包含"JavaScript"，""等敏感字符。以及对字符串中的<>:"&/'等特殊字符做处理.

3. 输入检查

原理：一般来说除了富文本输出之外，在变量输出到 HTML 页面时，使用编码或转义的方式来防御 XSS 攻击

解决方案：

* 针对 HTML 代码的编码方式：HtmlEncode
* PHP：htmlentities()和 htmlspecialchars()两个函数
* Javascript：JavascriptEncode（需要使用""对特殊字符进行转义，同时要求输出的变量必须在引号内部）
* 在 URL 的 path（路径）或者 search（参数）中输出，使用 URLEncode

## CSRF 的攻击方式

浏览器所持有的策略一般分为两种： Session Cookie，临时 Cookie。保存在浏览器进程的内存中，浏览器关闭了即失效。 Third-party Cookie，本地 Cookie。服务器在 Set-Cookie 时指定了 Expire Time。过期了本地 Cookie 失效，则网站会要求用户重新登录。

GET, POST 请求

* 这里有个误区 大多数 CSRF 攻击，都是通过  、 、 \<script> 等带 src 属性的标签，这类标签只能发送一次 GET 请求，而不能发送 POST 请求，由此也有了认为 CSRF 攻击只能由 GET 请求发起的错误观点。

构造一个 POST 请求，只需要在一个不可见的 iframe 窗口中，构造一个 form 表单，然后使用 JavaScript 自动提交这个表单。那么整个自动提交表单的过程，对于用户来说就是不可见的。

## CSRF 的防御方式

1.验证码 原理： CSRF 攻击过程中，用户在不知情的情况下构造了网络请求，添加验证码后，强制用户必须与应用进行交互

* 优点：简洁而有效
*   缺点：网站不能给所有的操作都加上验证码

    2.Referer Check

原理：

* 利用 HTTP 头中的 Referer 判断请求来源是否合法
* Referer 首部包含了当前请求页面的来源页面的地址，一般情况下 Referer 的来源页就是发起请求的那个页面，如果是在 iframe 中发起的请求，那么对应的页面 URL 就是 iframe 的 src
* 优点：简单易操作（只需要在最后给所有安全敏感的请求统一添加一个拦截器来检查 Referer 的值就行）
* 缺点：服务器并非什么时候都能取到 Referer 1.很多出于保护用户隐私的考虑，限制了 Referer 的发送。 2.比如从 HTTPS 跳转到 HTTP，出于安全的考虑，浏览器不会发送 Referer

使用 Anti CSRF Token

原理：把参数加密，或者使用一些随机数，从而让攻击者无法猜测到参数值，也就无法构造请求的 URL，也就无法发起 CSRF 攻击。

例子（增加 token）：

* 比如一个删除操作的 URL 是：`http://host/path/delete?uesrname=abc&item=123`
* 保持原参数不变，新增一个参数 Token，Token 值是随机的，不可预测
* http://host/path/delete?username=abc\&item=123\&token=\[random(seed)]
* 优点：比检查 Referrer 方法更安全，并且不涉及用户隐私
* 缺点： 加密 1. 加密后的 URL 非常难读，对用户非常不友好 2. 加密的参数每次都在改变，导致用户无法对页面进行搜索 3. 普通参数也会被加密或哈希，将会给 DBA 工作带来很大的困扰，因为数据分析常常需要用到参数的明文 token 1. 对所有的请求都添加 Token 比较困难

4. 其他安全问题

4.1 跨域问题处理

当服务端设置 'Access-Control-Allow-Origin' 时使用了通配符 "\*",允许来自任意域的跨域请求，这是极其危险的

4.2 postMessage 跨窗口传递信息

postMessage 允许每一个 window（包括当前窗口、弹出窗口、iframes 等）对象往其他的窗口发送文本消息，从而实现跨窗口的消息传递。并且这个功能不受同源策略限制。

必要时，在接受窗口验证 Domain，甚至验证 URL，以防止来自非法页面的消息。实际上是在代码上实现一次同源策略的验证过程。接受窗口对接口的信息进行安全检查。

4.3 web Storage

Web Storage 分为 Session Storage 和 Local Storage。

虽然受同源策略的约束，但当存有敏感信息时，也可能会成为攻击的目标。
