项目背景
最近在开发一个微信公众号商城,在调用下单、支付、查询订单等等接口时,须要验证用户的身份。微信提供了openid做为识别用户身份的凭证,能够结合openid设计一套用户身份权限认证机制。考虑到安全性和易实现程度,备选的方案有Session认证机制和Token认证机制,本文在比较了二者的特色后选择了Token认证机制,而后详细阐述了如何实现Token认证机制。前端
接口设计
在寻找合适的认证方式以前,先说明一下项目先后端的设计。项目的先后端是分离的,前端使用AJAX的方式向后端请求操做资源(增、删、改);后端接口设计遵循RESTful API原则,结果以JSON格式返回。web
身份认证备选方案
Session认证
在web网站中,session能够将访客状态记录在服务器中,并分配一个惟一的session id给访客,并将该id附加在headers中返回给客户端。客户端接收到session id后,会将id存储在cookie,以后客户端每次访问服务器,传送的cookie中都会携带session id,服务器以此来识别访客的身份。
数据库
Token认证
token认证方式中客户端和服务器的交互过程与session的相似,客户端向服务端请求token,拿到token后,客户端能够在以后的请求中将token附加在header,以验证用户的身份和权限。
后端
比较两种认证方式
【此处应该列举诸多不一样,可是必定要提到为何token更适合,而不是session】api
- token认证更灵活。对于session认证,客户端每次发送求情都会发送cookie;而对于token认证,能够在须要身份验证的场景下才发送token。
- token容许多域名认证。cookie是绑定单域名的,在a域名生成的cookie没法用于b域名,因此session id没法做为不一样域名的共同认证id。而token认证则不受限制,token能够附加在任何请求上。
- 在客户端的存储方式不一样。session自动存储在cookie,而token则须要定义存储的方式。token一般能够存储在localStorage(永久存储,浏览器关闭时不清除token)、sessionStorage(浏览器关闭时token会被清除)、cookie。值得一提的是,即便将token存储在cookie,也能够免疫CSRF,由于cookie中的token并不用于认证。
- CSRF(跨站请求伪造)。认证免疫CSRF(跨站请求伪造),而session认证则存在遭受CSRF的可能性。
- 跨站脚本攻击(XSS)。相对于session认证,token认证更容易遭受跨站脚本攻击(XSS)。
本项目考虑到Token认证机制更灵活,例如token能够控制是否附加在请求、token自己能够进行自定义加密、能够将token存储在cookie之外的地方,因此选定Token认证机制做为商城应用的用户身份权限认证机制。浏览器
获取token的流程

- 客户端向服务端token接口提交code,请求获取token。此处的code是引导用户进入受权页面后微信服务器附加上去的,详细方法见微信公众平台的微信受权网页文档。
- 服务端经过code向微信公众平台换取用户的openid。微信受权网页有两种受权scope,本项目只须要用户的openid,不须要用户更多的信息,因此将scope设为snsapi_base。
- 微信公众平台向服务端返回了openid等等信息。
- 服务端生成token,将token和用户信息以键值对的形式存储后,服务端返回token给客户端。
存储token及用户信息的流程

- 服务端获取用户的openid后,在数据库中登记用户的信息,并取出用户的id。
- 服务端以token为key,以openid、user id、权限信息等为value,将该键值对存入缓存中。在存入缓存时,注意设置缓存有效时间,过长的有效期存在安全隐患,对于本项目,用户办理业务后短期内不会再访问,因此将token的有效期设置为2小时。
调用接口时的token认证流程

- 客户端将token附加在header,向业务接口发送请求。
-
业务接口在执行业务逻辑前,凭token验证用户的身份。分别验证如下三点:缓存
- token的合法性(有记录)
- token的有效性(没过时)
- Token对应的用户权限Auth
总结
Token机制的特色
- 使用灵活,能够选择性认证。
- 能够多个域名使用同一token认证体系。
- 在客户端的存储灵活,除了存储在cookie,还能够选择localStorage、sessionStorage。
- 免疫CSRF(跨站请求伪造)。
Token认证机制的三个流程
- 获取Token的流程。
- 存储Token及身份权限信息的流程。
- 调用接口时的Token认证流程。特别注意须要验证token的合法性、时效性、关联的用户权限。