Cookie,Session,Token,同源策略、跨域、XSS、CSRF、DNS劫持一次性搞明白
前端安全--用户身份标识
这是一块很多、很杂、而且关联性很强、难以理解的知识。这次把这块知识总结一下,彻底理清楚之间的逻辑关系。本文是我后期复习的复盘,有部分基础的知识可能没有详细讲解。
Cookie
为什么会出现cookie
由于HTTP是无状态的,也就是说服务器在收到请求之后,不知道是哪个客户端请求的,这样无法满足有些场景,比如下面这个场景
客户端添加购物车、去结算、下单,再添加购物车之后,服务端需要为该用户的购物车数据库中添加商品,去结算要为该用户生成订单,所以服务端会知道是哪个用户发来的请求。
于是cookie出现了,它是客户端的一小段存储空间(4KB),是存储空间!!!
我们在浏览器中的application选项卡中可以看到。注意,cookie是服务端通过set-cookie这个http响应头设置的!下面是我截取来自掘金的一段cookie,下面的字段没有一个不重要的:

set-cookie字段解释:
标题 | name | value | Domain | size |
---|---|---|---|---|
字段含义 | cookie的名字 | cookie的值 | 访问这个域会被带上 | cookie长度 |
SameSite
有三个值:strict Lax None(必须带上Secure),常用来预防CRSF(后面说)
HTTP-only
限制不能通过JS读取到该cookie,预防XSS攻击(后面说)
Expires
cookie的过期时间,绝对时间,就是说几点几分几秒这个cookie就过期了,HTTP1.1之前使用Expires,那老技术肯定就有问题:
1.客户端服务端时钟不一致,
2.服务端需要计算出一个具体时间,服务器压力大
Max-age
相对时间,几个小时之后cookie就过期了。这个好!但是HTTP1.1才提出,旧浏览器不兼容。
Session
为什么会出现Session
Cookie很重要,因为它标识用户的身份,想想如果别人拿着你的cookie就可以登录淘宝,去把你购物车清了!所以一定要保护好,虽然有HTTP-only,SameSite等一系列预防的手段。但是将这么重要的东西存在浏览器,总归是不安全的,所以就出现了session。
Session是什么
session顾名思义,会话。当用户访问服务器,就开始了一次会话,这个时候服务器为用户生成一个session(会话),sessionID 表示这个会话的唯一标识。服务端将sessionID返回给浏览器,浏览器存储到cookie中,下次访问Domain下的域名时会带上。服务器通过sessionID判断用户的身份。
当用户关闭浏览器,会话结束,浏览器会删除sessionID,服务器会保持一段时间,防止用户短时间再次访问服务器。
session会有什么问题?
1 如果用户多,服务器存储压力大。
2 由于负载均衡,用户的请求可能会被分配到不同的服务器,这个时候会存在访问到的服务器不存在该用户session的情况,需要做服务器之间的session同步。
Token
token是用于做用户身份验证,但是它是明文传输的,它唯一的作用就是防止篡改。token可以存在cookie中,也可以存在localstroage中,不care。
Token的构成如下所示(以JWT为例): 由三部分组成:Header、payload signature。不熟的同学去看一下。
Header和payload是明文传输,只是base64编码,很容易就解码, signature是将前两者通过加密算法和密钥来生成的,是为了防止篡改的!!服务端收到token之后拿着自己的密钥来解密,获取到Header和payload(可能是对称加密也可能是非对称加密(不懂的参考HTTPS))
总结
cookie是浏览器的一小块存储空间,session是为了解决cookie不安全的问题出现的,但是又造成了新的问题。token是用来做身份校验的令牌,他跟前两个压根就不是一个维度的东西。JWT是token的一种。上面这三个
前端安全--浏览器策略
因为各种攻击的存在,浏览器需要制定一定的策略,那么这个策略就是同源策略。
同源和跨域
同源是指两个URL的协议、域名、端口号都相同,浏览器在当前所处的域下(就是你目前在看的这个网页),去访问跨域的资源(协议域名端口号不同的资源),就会发生跨域,请求不到资源,浏览器报错。HTTP实行同源策略,websocket不实行,不存在跨域的问题。
可能的误解
1.浏览器只会对AJAX请求做出跨域限制?
错误:浏览器对于JS、图片、AJAX都会做出限制,只是对AJAX的限制比较大,所以一般谈到跨域人们会认为是对AJAX的限制
2.如果一个请求跨域了,浏览器就不会发送这个请求了?
错误:请求还是照样发,而且服务端资源还返回了,但是浏览器会在最后一道关卡做拦截,不会呈现到页面,比如跨域的图片不呈现,跨域的脚本不执行。
跨域的解决方法:
因为讨论的是安全问题,这部分不细说,主要有以下几个方法:
1.CORS:服务端配置Access-control-Allow-Orign响应头,允许访问的客户端,配置*表示允许所有的client访问。
2.正向代理服务器:客户端自己使用nodejs搭建一个服务器,由于服务器之间是不存在跨域的!我只需要访问我自己的服务器,服务器去与资源服务器要资源就行。
3.反向代理nginx:原理跟2一样,只是服务器是后端那里配置的,隐藏服务器的身份。
4.JSONP:一种很巧妙的方式,利用浏览器对script标签限制小的特点。因为这个要会手写,所以就不讲了。不会写的可以去看一下。
5.websocket:这个使用的是ws,wss,该协议不实行同源策略。
6.iframe是一个HTML元素,它允许您在当前网页中嵌入另一个网页。我们引入iframe网页将document.damain设置相同可以解决跨域。
前端安全--网络攻击
CRSF(跨站请求伪造)
整个流程
1.用户访问银行网站,银行网站a.com会返回一个cookie给用户,cookie存储在浏览器端,下次作为用户的身份标识。
2。用户没有退出银行网站(cookie一直在),用户点击了恶意链接b.com,b.com会向a.com发起一个请求,这个请求往往会携带一些操作,比如转账。
3.因为用户已经有a.com的cookie了,所以浏览器压根就直接转发b.com的请求,a.com服务器收到请求,校验cookie,发现是用户发来的请求,所以就执行转账操作。
4.用户整个过程不知情,只是点击了一个链接。
疑虑
1.为什么b.com请求a.com不会跨域?
浏览器的同源策略禁止了不同域名下的资源共享,但是它不禁止跨域请求,只是发起一个请求,不是要返回资源,CRSF攻击者的目的是自定义的操作。
2.CRSF的本质是什么
攻击者利用用户已经访问的凭证(cookie)、浏览器会自动带上cookie、服务器只校验cookie这三点,骗过了服务器,用户完全不知情。
解决办法:
1.同源检测
服务端对HTTP请求头中origin的referer做检测,判断请求是不是允许访问的域。
2.为cookie设置SameSite属性
SameSite设置为Lax或Strict,一般都是Lax。
3.CRSF Token
解决cookie单一验证的方式,服务端生成token返回给客户端。客户端在下次请求的时候在HTTP请求头里带上这个token,然后服务端session里面存了token可以做校验,但是会有负载均衡的问题,请求可能会被分配到没有相应token的服务器。
4.双重cookie
为了解决CRSF token服务端存储的压力,所以采用双cookie,将cookie在请求域名中带一个,服务端比较两者是不是一样。利用攻击者无法获取cookie,也就无法在URL中添加cookie。服务端校验不通过。
XSS(跨站脚本攻击)
反射型
场景1.恶意攻击者在input框输入下面的代码:
`http://xxx/search?keyword="><script>alert('XSS');</script>`
服务端将恶意代码拼接到HTML中返回,浏览器执行,恶意代码执行,可能是获取用户的cookie。
解决办法
对敏感字符做转义比如大于小于引号
场景2.a链接中输入javascript开头的代码
<a href="javascript:alert('XSS')">跳转...</a>
转义已经无济于事,采用白名单机制,限制a链接中出现javascript开头的代码
存储型
场景 发表评论
用户发表评论,含有恶意代码,存储到后台数据库,当其他用户访问该评论,数据库就会返回恶意代码执行,比如获取cookie。
DOM型
场景
用户在input输入恶意代码,前端JS拿去执行了。比如vue中可以双向数据绑定,拿到用户输入,v-html这个就可能造成XSS攻击。
解决办法:规范前端代码
XSS的解决办法
1.字符过滤与转义
对输入的敏感字符进行过滤或转义,浏览器就不会把这些字符当代码执行,而是当成文本。需要注意转义规则和转义时机,转义太严格,正常代码被转义导致乱码,转义太宽松,恶意代码未被转义,造成安全隐患。
转义时机有以下三个:用户输入,写入数据库时,前端呈现到页面时。之前转义可能会被多次转义,而且出现页面呈现错误的情况。最好在呈现页面时转义最好用成熟的转义库,不要自己写转义规则。
2.CSP 白名单策略
CSP(内容安全策略)实质就是白名单策略。开发者明确告诉客户端,哪些外部资源可以被加载和执行。就是网页上的保安。
3.保护cookie
为cookie设置HTTP-only属性,保证它不会被JS读取。
DNS劫持
这个是违法的。就是通过一些手段将用户的域名访问劫持 返回错误的 ip 地址 给用户返还自己恶意服务器上的资源。轻则返回一些广告 重则做一个克隆网站 用户以为是真的 然后输入敏感信息被盗号。
一个良性DNS劫持--CDN
用网上的一张图:

转载自:https://juejin.cn/post/7235274652728442941