鉴权与Web安全
网站常见的鉴权认证方式有哪几种?本文主要覆盖内容
Session认证的原理
JWT认证的原理
Auth2认证的流程
和JWT相比Session机制有哪些缺点
Session机制如何能尽量保证安全
针对Web的攻击技术
XSS攻击原理
CSRF攻击原理
服务器需要一些信息来区分用户(鉴权和认证)
Session鉴权注册流程
- 用户注册
- 服务器查看是否有此用户,如果有则更换用户名,否则存储注册信息(存储明文密码的风险(脱库--数据库被攻破,所有信息暴露),存储密文,即对密码(可以在密码上再次拼接一些随机内容--这些内容也保存在数据库)进行再次加密)
- 用户注册成功
- 用户登录
- 服务器判断是否有此用户,如果有计算出它的密码,和数据库存的密码是否相同。创建一个session对象(存在内存或数据库--用户量大),把session_id通过setCookie来给到客户端
- 登录成功,响应报文头中有
Set-Cookie
字段,那么设置这个cookie - 再次请求这个网站,cookie会自动被浏览器带上(请求),头中有
Cookie
字段 - 服务器看到请求报文中有Cookie,会拿出其中的session_id,然后查询出这个id对应的是哪个用户并发回去
- 拿到自己的数据
保证Session安全的策略以及Session的缺点
Cookie泄露到攻击者那里,攻击者可以通过session_id来伪造成某用户。如果网站有xss漏洞(攻击者将js代码提交到网页上,刷新网页js执行),这种情况下他通过document.Cookie
就能拿到用户的Cookie(发送ajax请求)
解决方法:
- 服务器在setCookie的时候加一个http-only,这种情况下js无法获取到当前页面Cookie
- https协议,加一个secure字段,即只有http请求才会带cookie
Session认证的缺点:
- 只能应用在浏览器的场景(只有浏览器发请求会自动带上cookie),小程序或一些app、终端、服务端模拟登录等场景就不能使用。即不通用是最大缺陷
- session对象占用资源很多(内存或数据库--redis),如果是分布式服务,即请求到达的服务器不同,需要对数据库访问进行设计--成本高
- 服务器压力大
JWT鉴权登录流程
JWT(JSON web token)
- 客户端登录
- 数据库做用户名和密码验证。如果验证通过需要生成一个token,由三部分构成(str1.str2.str3),str1是一个json(typ:jwt, alg:hs256)加密(Base64)后的内容,str2是一个json(username,exp-其它信息,尽可能少)加密(Base64)后的内容,str3是一个
HMAC(str1+.+str2,secret_key)
返回的内容,secret_key
是存在服务器上的。在头中加入jwt_token
字段。服务器什么都不用存 - 登录成功,浏览器需要存下来,各种存储空间都可以
- 发请求时,要加上jwt_token参数(直接放到请求内容中),或者放到请求头中(Authorization)
- 服务器要计算token是否有效,HMAC函数重新计算一遍,与客户端传来的参数做比较,如果有效,就拿出第二部分(str2),查看过期时间(是否过期),如果过期就返回过期提示,否则提供请求的信息
- 客户端拿到请求
和Session比较
优点:
- 通用,只要客户端有存储空间即可
- 服务器存储压力小
缺点:
增加了服务器的计算压力
JWT的其它问题:用户点了注销之后token并没有失效,则此token还可以冒充一个有效用户,所以注销要需要额外操作,此外token的过期时间设置也需要一个良好的策略,此时发现JWT的实现也会让服务器做出不少额外操作
Auth2鉴权
在没有注册的情况下使用其它系统的鉴权功能来进行登录,例如qq登录、微信登录等
网站W 认证服务器G 用户U
- 网站要在认证服务器上登记(注册一个小应用),表示以后需要在这里获取用户信息,登记一个
client_id
,一个密钥secret_id
(类似名片) - 用户在此网站登录,网站要求用户拿着之前的名片去找服务器要允许凭证(即用户允许网站访问他的数据)
- 用户允许网站从服务器访问他的数据
- 服务器会询问用户,网站需要你的xxx信息,你同意吗?(可能是询问框,或者当你在服务器登录也默认你是允许的)
- 用户确定
- 服务器将凭证给用户,让网站通过此凭证来拿数据
- 用户将此凭证给网站
- 网站通过自己的名片、自己的密钥、用户的名片来去服务器访问用户的数据,拿到一个通行令牌
- 服务器将通行令牌给网站
- 网站拿着这个通行令牌去服务器拿数据
- 服务器返回数据
Auth2的合理性分析:
- 网站要获得用户的同意
- 用户仅统一网站在服务器获取数据
- 网站必须拿着名片和用户的凭证才能拿用户的数据
- 令牌是为了简化后续网站和服务器交互中使用的数据
XSS是什么?
XSS(cross-site scripting)
举例描述:
正常用户A在网站上留言,用户B看到此留言,此时没有XSS
恶意用户提交评论(<script>console.log('xxx')</script>
),用户B访问此网站,这段脚本直接在B的浏览器运行,那么恶意用户可以任意操作B的Cookie,B却不知道,此时恶意用户可以伪造成此用户发送请求到服务器访问B的隐私
成因:
- 后台模板问题(对页面不做过滤,直接把所有数据打印出来),这种情况下只要把
<
换成<
(HTML实体)即可 - 前端代码问题(
p.html
),解决方法是尽量不手动拼接,而使用text
方法,一定要使用html,把可疑元素转换为HTML实体。在大量创建dom节点的情况下,先将节点创建出来,再使用innerText
属性来填充内容
ps:js中不要使用eval,尽量不使用innerHTML,所有用户输入的地方都不安全,所有显示用户输入内容的地方都不安全
防范xss的根本在于页面上不允许存在用户自定义的可以执行的脚本存在
CSRF攻击
CSRF(cross-site request forgery)
用户不知情的情况下调用了某个接口,因为用户处于登录状态,所以服务器认为这个请求是合法的,此时用户受到了攻击。<img src='xxx' onload=func()>
在图片加载的时候会调用这个函数,用户就会被迫发出请求
防范方案:
- 在渲染页面的时候生成一个随机数,放到页面中,例如
<input type=hidden name=_csrf_token value=xxx />
- 服务端setCookie,将这个随机数种入浏览器
- 服务器规定浏览器(此网站前端)发任何请求都要带上这个参数
- 后台在接收请求时,通过cookies拿到这个值,验证是否和此用户请求中携带的随机数相同