认证和授权
认证-Authentication
认证是对用户身份的验证,通过对用户凭据的校验识别用户身份的合法性。常见的认证方式有用户名(邮箱、手机号等)/密码 手机验证码 微信/支付宝扫码 生物识别 等。认证通过后一般会返回一个唯一身份标识,比如输入手机号、验证码登录成功后,系统返回一个 token。
授权-Authorization
授权是指用户访问系统资源的权限,授权发生在用户认证之后,实现授权的方式一般需要通过载体。比如在现实中,出去旅游时提前在网上订好酒店,去酒店办理入住时:
- 在前台出示订单和身份证是身份认证
- 前台确认过你的订单和身份一致,给你一张可以进入707房间的房卡,就是通过房卡向你授予707房间的使用权
- 你拿着房卡去707房间刷卡验证就是
鉴权,刷卡鉴权通过就可以进入房间
在系统中同样,使用用户名/密码(或其他方式)成功登录系统,返回一个 access_token,后续所有请求使用 access_token 访问系统资源。
授权实现方式
#cookie #session #token #jwt
Cookie
用户身份认证通过后,服务端生成用户登录成功信息 setCookie() 后返回客户端,客户端的后续请求都要带上 cookie 内登录信息,优点是在服务端未存储用户登录信息,节省空间、提升鉴权的性能;缺点是有安全隐患(XSS,XSRF)
Session
Session 是基于 cookie 实现的,不同在于服务端存储用户登录状态,生成 sessionId 用于与客户端交互和身份标识。优点是比 cookie 方式安全,但访问量过大会对服务器造成压力。
Token
与上两种类似,使用 access_token 也分为服务有状态和服务端无状态(JWT)两种。
服务端有状态
- 为每一个用户生成一个 token, 比如使用 uuid 生成一个最简单的 token;或者使用 user_id + timestamp + random_str 进行MD5等
- 将 token 与用户的映射关系、有效期等信息存储到数据库(不推荐)、缓存中
- 验证 token 时先根据 token 查询用户登录信息,token 不存在或者已过期时,验证不通过
服务端无状态(JWT)
与服务端有状态方式不同,使用 JWT 方案时生成 token 后不在服务端存储,签名处理后直接发送到客户端。
什么是JWT
优点
- 节省存储资源:服务端不存储用户 token,可以节省服务器存储资源,降低成本
- 提升性能:JWT是自包含的,可以将一些非敏感信息直接存储在 token 中,可以直接解析使用而不用查库或redis 等存储资源
缺点
- token 是直接存储在客户端的,服务端无法销毁,不能快速的人为失效
- 安全性:如果因开发不严谨等将一些敏感信息存储到了 token 里,容易造成泄密
Token 刷新
jwt 服务端无法销毁,不适合签发一个长时效的 token,但频繁的重新认证又是一个糟糕的体验,这时可以引入 refresh_token 来优化授权流程
- 在签发 access_token 的同时,签发一个 refresh_token
- access_token 是一个短时效的验证 token,用于所有请求的验证
- refresh_token 是一个长时效的专用 token,一旦 access_token 已经过期或即将过期,可以用 refresh_token 去请求一个新的 access_token, 只有 access_token 和 refresh_token 都过期了才需要用户重新认证
当然其实私以为这也是个权宜之策,最好的方式是根据场景需求选择合适的 token 策略,各取所长。比如一些内网请求、一些专有网络下请求的APP,高并发要求极高的查询请求等可以充分使用到 jwt 优点的请求完成可以使用 JWT。