浅析权限认证中的有状态和无状态

前言

咱们在设计构建一个系统的时候,权限管理和用户认证是最基本功能,其中关于用户认证这块是一个比较常见的模块。在已有的方案中,咱们最多见的就是保存到 tomcat 中的 session 对象中。随着微服务的兴起,一种新的认证方法又火了起来,那就是JWT,下面我就浅析下本身对两种认证方式的认识,一些经验和你们探讨。web

浅谈认证

我对认证的理解就是,当一个设备(客户端)向一个设备(服务端)发送请求的时候,服务端如何判断这个客户端是谁。传统意义有两种认证方式:有状态认证、无状态认证。有状态和无状态最大的区别就是服务端会不会保存客户端的信息。面试

有状态认证

有状态的认证,以 cookie - session 模型为例,当客户端第一次请求服务端时候,服务端会返回客户端一个惟一标识(默认在cookie中),并保存对应的客户端信息。客户端接受到惟一标识以后,将标识位保存到本地cookie中,之后的每次请求都携带此 cookie ,服务端根据此 cookie 标识能够判断请求的用户是谁,而后查到对应用户的信息,大概示意图以下:redis

请求认证过程(以tomcat为例):

一、客户端向服务端发起请求;算法

二、第一次客户端发起请求,服务端建立一个 key 为JSESSIONID的值,并写入到客户端的cookie中,同时在服务端的Session Manager中建立一个对象,保存这个 JSESSIONID 对应的信息;spring

三、之后客户端每次请求,都会根据cookie进行区别,咱们能够经过 session.setAttrbutie,session.getAttrbuite 等方法,拓展用户信息,根据用户信息作一些业务判断等;数据库

四、Session Manger 中维护有一个定时器,当 JSESSIONID 对应的信息长时间没有访问(默认30分钟),或者显性调用 session.invalidate 方法,那么这个对应的信息将会被删除。跨域

那么针对有状态的认证,咱们分析下他的利弊:浏览器

优点

由于客户端的信息都保存在服务端的 Session Manager 中,若是要将客户端的认证信息取消,只须要将对应的session 信息删除便可,及时响应,方便快捷。缓存

劣势

一、由于服务端保存着客户端的信息,当用户量特别多时候,服务端须要特别的内存资源;tomcat

二、若是失效时间特别长的状况下,大量资源被占用没法释放,若是释放,那么至关于用户的注销登陆;

三、客户端的信息在服务端中维护,若是服务端为集群的场景下,那么客户端信息不共享,必须使用分布式 session 或者其余方案;

四、cookie有同源策略和跨域限制,部分业务场景下cookie并不能传递;

五、部分设备自己不支持cookie或者禁用cookie,还有的手机浏览器也不支持cookie。

应用实战

一、若是公司以集群式部署多台服务,那么能够采用的策略有:配置负载均衡的路由策略为hash一致算法(不推荐),若是某个机器停机,那么会从新分配到新机器,又须要从新登陆;session复制方式(不推荐),复杂度太高;分布式 session 方案(强力推荐),目前市场上有 spring-session 的依赖,能够将 session 保存的容器从应用内部抽取到 redis 或者 数据库中供多个应用使用,实现集中管理,为了保证设备的兼容性,spring-session提供了将认证方式从cookie修改成header,web网站能够保存到 SessionStorage,移动端能够保存到本地缓存中。

二、若是一个公司有多个产品须要共享认证信息,此时须要使用 SSO Server。

无状态

无状态的认证,客户端在提交身份信息,服务端验证身份后,根据必定的算法生成一个 token 令牌返回给客户端,以后每次请求服务端,客户端都须要携带此令牌,服务端接受到令牌以后进行校验,校验经过后,提取令牌中的信息用来区别用户,大概的示例图以下:

请求认证过程:

一、执行登陆操做,用户端发送帐号密码等信息;

二、服务端校验帐号密码是否正确,若是正确,根据对应的用户信息和服务端秘钥生成 JWT 令牌,而后经过response.setHeader 返回给客户端(此处假设生成了一个名为 x-auth-token 的令牌);

三、客户端在返回成功以后,将Header中的x-auth-token 保存到本地的LocalStorage中;

四、客户端在之后每次请求服务端时候,都在header中携带x-auth-token令牌的值;

五、服务端每接受到请求以后,判断hader中是否包含x-auth-token,token 是否有效,而后经过 BASE 64 算法 decode,根据解密后的参数,判断当前 token 是否在有效期,所访问的接口是否有权限等操做。

优点

一、由于服务端不保留客户端的任何信息,每次只须要经过特定的算法进行校验,节省了大量存储空间;

二、方便水平扩容,不须要 SSO Server,只要保证新的应用采用一样的验证算法,就能够验证经过并得到对应信息。

劣势

当客户端的token被盗用,或者须要手动封禁某个用户的时候,没办法对此token进行操做,必须等待token失效(若是在服务端维护token和用户的关系,技术能够实现,可是违背无状态的设计理念)。

应用实战

一、生成的 token 中携带用户经常使用信息,可是不携带用户的敏感信息,好比密码手机号等等,由于这些信息经过BASE 64 能够解密出来的;

二、要处理服务端主动禁用某个 token ,能够采用黑名单措施,每次请求前判断当前token是否已经被禁用;

三、token 中的信息除了基本信息外,还应该携带好比签发时间、有效时间、刷新token等字段,用来处理token的续约问题。

总结

在实际的项目中,咱们该如何选择认证模式,是有状态的认证仍是无状态的认证呢?之前看文章时候,在掘金中看到有人把 JWT 批评的一无可取,就和垃圾同样。我我的以为吧技术没有谁好谁坏,谁旧谁新,也没有谁该被时代淘汰,存在及合理,咱们须要充分理解需求,合理使用技术,只有最合适的技术才是最好的选择。 下面是我关于技术选型时候的一些我的观点,但愿你们批评指正和交流。

在个人经验中,目前比较流行的就是互联网APP中大部分采用 JWT 的认证方式,一些企业内部管理系统则大部分采用 cookie-session 的机制,大量的商业案例下,我我的分析推测的缘由可能以下:

一、在互联网APP产品中,尤为以 to C 模式,用户量极大,为了用户体验,通常会将登陆信息保留特别长时间,某些APP 只要你不卸载,那么无论几个月以后登陆,帐户仍是处于登陆状态。在这种状况下,假如采用 cookie-session 机制,那么你的用户信息保存不少个月,用户量特别大的状况下,会形成大量资源占用和浪费,这种场景采用 JWT 就是相对比较好的方案。

二、企业内部管理系统有如下特色:用户量较少(最多最多不超过10W人),信息安全要求高(及时踢出客户端登陆状态,我的浏览器关闭帐号退出登陆),在这样的场景下占用的内存不会太多,因此基于 cookie-session 这种机制,是比较好的方案,若是企业内部还有其余应用须要集成时候,须要使用 SSO Server 实现。

代码案例

最近在找工做,若是闲下来有时间的时候会写两个项目出来,敬请期待:

一、 spring security + JWT 的验证案例

二、shiro + spring-session (header替换cookie)的验证方案

ps:蚂蚁5面技术过了,期待hr面试的早点到来,给本身加油。

相关文章
相关标签/搜索