相关概念
同源政策及其规避方法
认证 Authentication
验证当前用户的身份
常用的认证方式
- 用户密码登录
- 登录链接
- 验证码
授权 Authorization
用户授予第三方应用访问该用户某些资源的权限
app授权(访问文件资源 地理位置) 小程序授权(获取头像 地区 性别)
凭证 Credentials
- 实现认证和授权的前提
- 需要一种媒介来标记访问者的身份
三者关系
HTTP请求是一个无状态的协议
认证就是用户证明自己是自己
因为HTTP无状态,用凭证来维持用户的登录状态,登录后每次都用凭证告诉服务器用户已经登录
cookie的基本知识
session的基本知识
大部分情况下,session是基于cookie实现的,session存储在服务器端,sessionID会被存储到客户端的cookie中.
sessionID的传递方式(了解即可)
- 通过URL
- 通过Cookie
- 通过SSL
- 通过隐藏表单:在表单中设置一个隐藏域,将sessionID放入,提交表单时一起提交给服务器.
session coookie的区别
-
安全性
session>cookie因为session存储在服务端 -
存取值的类型
cookie只支持字符串数据,要想支持其他类型的数据,需要转换成字符串.二进制用base64session可以存任意类型 -
有效期 cookie可以长时间保持,session一般失效时间比较短
-
存储大小
session>>cookie
OAuth的基本知识
身份认证机制
cookie
cookie认证机制
过期cookie会被删除
安全隐患
服务器常常设置Set-cookie:authed=true 通过一些软件,可以将Cookie字段设置为authed=true,来发送HTTP请求,由此来欺骗服务器
防篡改机制
服务器为每个Cookie项生成签名,防止Cookie被篡改. 例子如下
1.在服务器中配置一个不为人知的字符串(我们叫它Secret),比如:x$sfz32。
2.当服务器需要设置Cookie时(比如authed=false),不仅设置authed的值为false, 在值的后面进一步设置一个签名,最终设置的Cookie是authed=false|6hTiBl7lVpd1P。
3.签名6hTiBl7lVpd1P是这样生成的:Hash(‘x$sfz32’+’false’)。 要设置的值与Secret相加再取哈希。
4.用户收到HTTP响应并发现头字段Set-Cookie: authed=false|6hTiBl7lVpd1P。
5.用户在发送HTTP请求时,篡改了authed值,设置头字段Cookie: authed=true|???。 因为用户不知道Secret,无法生成签名,只能随便填一个。
6.服务器收到HTTP请求,发现Cookie: authed=true|???。服务器开始进行校验: Hash(‘true’+’x$sfz32’),便会发现用户提供的签名不正确
因为cookie是明文传输,只要服务器设置过一次就知道true的签名了.因此cookie中最好不要放敏感数据.一般来讲Cookie中只会放一个session.
使用cookie需要注意的问题总结
- 存储在客户端,容易被篡改,使用前需要验证合法性
- 不要存储敏感数据
- HTTP下明文传输
HttpOnly能提高安全性,但不能一劳永逸- 注意cookie的大小<4KB
- 通过domian path的使用,减少数据传输
- 不可跨域(domain设置可以使次级域名不同的网址共享)
- 移动端对cookie支持不好,session基于cookie实现,移动端常用token
session-cookie
从上一个小节可以知道,cookie存在一定的安全隐患,为了解决这个问题,出现了session机制
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息
session认证机制
session机制的缺陷
- 安全性不佳 sessionID作为Cookie存储在浏览器端.攻击者可以利用本地cookie进行欺骗和CSRF攻击. 比如开发者没有正确关闭会话.用户关闭会话时应当删除传递sessionID的cookie,同时撤销服务器端的session内容.
- 拓展性差 单机可以正常使用.但是在服务器集群的情景下,要求session数据共享
- 跨域问题 跨域的服务导向架构.需要session共享,需要解决cookie的跨域问题
- 性能问题 session被保存在服务器端,如果短时间内有大量用户,会影响服务器性能,需要定期清理过期session
session共享方案
Nginx ip-hash策略
服务端使用Nginx代理,每个请求按访问IP的hash进行分配.来自同一IP固定访问一台后台服务器
优点:不对session做任何处理
缺点:缺乏容错性. 如果访问的服务器发生故障,用户被转移到第二个服务器上时,session会失效
适用场景:发生故障对用户影响小;服务器发生故障是低概率事件.
session复制
任何一个服务器上的session发生改变,该节点会把这个session的所有内容序列化广播给其他节点
优点:可容错,各个服务器都能及时响应
缺点:对网络负荷造成压力,如果session量大的话可能造成网络堵塞,拖慢服务器性能
session共享(主流)
Memcached或Redis集群缓存session- 把
session放到Redis中存储,虽然架构上变得复杂,并且需要多访问一次Redis.优点: 可以水平扩展(增加Redis服务器),服务器重启session不丢失,可以跨平台(网页端和APP)session共享
session持久化
将session存储到数据库中
优点:服务器出现问题session不丢失
缺点:如果访问量大,对数据库造成很大的压力
session的删除
除非程序同制服务器删除session,否则服务器会一直保留,一般都是在用户log off时删除session.
浏览器关闭不会主动在关闭之前通知服务器它即将关闭,所以并不是浏览器或者窗口关闭时session自动删除.
大部分session都使用cookie来保存sessionid,会话级别的cookie会被销毁,sessionid丢失,造成关闭浏览器session被删除的假象.
Token
token是很宽泛的概念,一般用来表示经过验证之后得到的凭证.
token有多个具体的标准比如OAuth Token JSON Web Token
可以解决的问题
- 避开同源策略
- 避免
CSRF攻击 token可以是无状态的,可以在多个服务之间共享- 对移动端支持好
存储位置
localStorage``sessionStorage
Acess Token
访问资源接口(API)时所需要的资源凭证
简单
token的组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
Acess Token认证流程如下
- 每次请求都要带上token(Header
Authorization字段) - 服务端不存放token数据,减少频繁查询数据库
也有储存在服务端数据库的 不采用算法的方式进行校验
Refresh Token
refresh token 是专用于刷新 access token 的 token。如果没有 refresh token,也可以刷新 access token,但每次刷新都要用户输入登录用户名与密码,会很麻烦 有了 refresh token,可以减少这个麻烦,客户端直接用 refresh token 去更新 access token,无需用户进行额外的操作。
Refresh Token的使用如下
Refresh Token 及过期时间是存储在服务器的数据库(或者缓存服务器或者内存)中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。
JSON Web Token (JWT)
- 目前流行的
跨域认证解决方案 - 一种认证授权机制
- 详细了解可看JSON Web Token 入门教程
JWT , Token的相同和不同
相同点
- 都是访问资源的令牌
- 都记录了用户的信息
- 服务端无状态
- 验证成功才可以访问服务端资源
不同?
查了很多资料,不确定 也有说token在验证的时候服务器只负责验证,不需要查库
token 验证时,需要根据token获取用户信息,然后验证token是否有效
JWT验证时,服务端只需要使用密钥解密即可,对数据库的压力更小.