当前位置: 首页 > 后端技术 > PHP

基于token的用户权限认证机制——以微信公众号授权网页为例

时间:2023-03-29 18:31:02 PHP

项目背景最近在开发一个微信公众号商城。在调用下单、支付、订单查询等接口时,需要对用户进行身份验证。微信提供openid作为识别用户身份的凭证,结合openid可以设计一套用户身份和权限认证机制。考虑到安全性和易实现性,备选方案包括Session认证机制和Token认证机制。本文在比较两者的特点后选择了Token认证机制,然后详细阐述了如何实现Token认证机制。接口设计在寻找合适的认证方式之前,先说明一下项目前后端的设计。项目前后端分离,前端使用AJAX向后端请求操作资源(增删改查);后端接口设计遵循RESTfulAPI原则,结果以JSON格式返回。IdentityAuthenticationAlternativesSessionAuthentication在网站中,session可以在服务器中记录访问者状态,为访问者分配一个唯一的sessionid,并将该id附加到headers中返回给客户端。客户端收到sessionid后,会将该id保存在cookie中,每次客户端访问服务器时,都会在传输的cookie中携带sessionid,服务器以此来识别访问者的身份.Token认证Token认证方式中客户端和服务器的交互过程与session类似。客户端向服务器请求令牌。客户端获得token后,可以在后续请求中将token附加到header中,以验证用户身份。和权限。比较两种认证方式【这里应该列出很多不同点,但一定要提到为什么token比session更合适】token认证更灵活。对于session认证,客户端每次发送请求都会发送一个cookie;对于token认证,只有在需要认证的时候才可以发送token。token允许多域认证。cookie是绑定单一域名的,在域名a中生成的cookie不能在域名b中使用,所以sessionid不能作为不同域名的通用认证id。但是token认证不受限制,token可以附加到任何请求上。客户端的存储方式不同。session自动存储在cookie中,token需要定义存储方式。token通常可以存储在localStorage(永久存储,token在浏览器关闭时不会被清除)、sessionStorage(token会在浏览器关闭时被清除)、cookies。值得一提的是,即使token保存在cookie中,也免疫CSRF,因为cookie中的token并不用于认证。CSRF(跨站请求伪造)。认证免疫CSRF(跨站请求伪造),而session认证有遭受CSRF的可能。跨站点脚本(XSS)。与会话认证相比,令牌认证更容易受到跨站脚本攻击(XSS)的攻击。本项目考虑到Token认证机制更加灵活。例如token可以控制是否附加到请求中,token本身可以自定义加密,token可以存放在cookie以外的地方,所以选择Token认证机制作为用户身份权限商城应用。认证机制。获取token,客户端向服务端的token接口提交代码,请求获取token。这里的代码是微信服务器在引导用户进入授权页面后附加的。详细方法参见微信公众平台微信授权页面文档。服务器通过代码从微信公众平台交换用户的openid。微信授权页面有两种授权范围。本项目只需要用户的openid,不需要用户的更多信息,所以scope设置为snsapi_base。微信公众平台向服务器返回了openid等信息。服务端生成token,将token和用户信息以键值对的形式存储后,返回给客户端。存储token和用户信息的过程服务器获取到用户的openid后,将用户的信息注册到数据库中,并获取用户的id。服务端以token为key,以openid、userid、权限信息等为value,将key-value对存入缓存。存入缓存时,注意设置缓存的有效期。过长的有效期可能会带来安全风险。对于本项目,用户在办理业务后短时间内不会再次访问,因此token的有效期设置为2小时。调用接口时的token鉴权流程客户端在header中附加token,向业务接口发送请求。业务接口在执行业务逻辑之前使用令牌验证用户的身份。分别验证以下三点:token的合法性(已记录)token的有效性(未过期)token对应的用户权限Auth总结token机制的特点是使用灵活,可以有选择地进行认证。多个域名可以使用同一个令牌认证系统。客户端的存储是灵活的。除了存储在cookie中,还可以选择localStorage和sessionStorage。对CSRF(跨站请求伪造)的免疫力。Token认证机制的三个过程获取Token的过程。存储Token和身份权限信息的过程。调用接口时的token鉴权过程。特别注意需要验证通证的合法性、时效性和关联用户权限。