JAVA的权限管控在平台化和企业化得过程中大体经过了如下的阶段:
权限系统功能上分为两部分:认证+鉴权。
1. 标准JAAS时代。在最早的时候,J2ee时代,Java提出了标准的鉴权服务,即jaas。tomcat,jboss,weblogic等容器都支持这一标准,只是配置略有不同。通过简单的容器配置和文件配置,通过一个LDAP(可以用数据库,只是效率不高),就可以提供一个极为高效便捷的权限管控服务。这个模式不仅支持页面管控,还支持ejb服务接口管控。非常高效。其鉴权因为ldap的数倍于数据库的查询效率而无需任何缓存,速度很快。业务系统的代码,没有任何入侵,当你仅仅只是想有有个简单和通用的鉴权模型,且各个系统互相隔离,甚至没有SSO,独立部署,并且并发量大,这种模式是最完美的。但是问题来了,第一,当应用的数量无限度增长,这种散落在各个容器的配置给容灾和修改,都带来了极大的挑战。其二,ldap的可读化差,修改和编辑极为不便,当需求一旦个性化超过了树能够表达的模型便很难在适应,也就是一旦超过过经典权限模型的范畴,便很难适应。其三,当ldap的数据爆炸式增长,且呈现28规律时(数据冷热不均),或者如果需要频繁的写ldap,查询效率会陡然下降。所以这种模式今天已经不是很流行了。但是在大量使用标准中间件产品的公司,包括银行都还大量部署这种模式的权限管控。实际上我们看到后来的SpringSecurity也是支持了这个标准的,只是不是基于容器,而是基于Spring的配置。
2.统一登录(SSO)+接口鉴权时代。既然分散的登录认证不能解决问题,那么很自然的就是统一登录,SSO,单点登录。权限系统通过引导将需要鉴权的系统引导到统一的登录中心,进行登录。那么问题就来了,这就需要权限系统能够保证登录风暴的压力。此外超过了经典权限模型的数据类型,必须要放弃LDAP转回到数据库,那么因为放弃了标准的jaas鉴权,那么权限系统就需要提供接口鉴权服务,或者依赖统一的分布式session,将权限在登录时注入进去。所以在去除jaas方式的ldap后,因为失去了ldap天然的高效检索能力(耗时约为数据库的百分之一),在经典的RBSC(基于角色的鉴权模型)下,如何最终将数据库格式化、规正化的权限数据,聚合和散列到:人-权限,就尤为重要。采取NOSQL或者各种这类扁平化的模型,使得鉴权服务能够一步拿到最终权限数据,是一种通俗的做法。但是,当无法解决数据散列和聚合问题的时候,如果存在登录风暴和海量鉴权诉求时,采用接口鉴权将有灾难性的后果。
3.统一登录(分布式Session)+接口鉴权时代。在回到分布式session:基于SSO的系统,因为没有共享session,所以系统间的跳转,都需要一次接口鉴权,而分布式session很好的共享和缓存了用户的权限信息。这是一个双刃剑,这是以牺牲用户权限的实时性,作为替代。同时,一旦分布式session出现技术问题,如果垮掉,后果不堪设想。此外分布式session比较适合经典的权限模型,一旦超出了这个领域,实际上就没法再预先注入所以数据,必须要提供鉴权接口。即:统一登录+接口鉴权。
此外,java标准鉴权模型没能很好的解决数据权限的问题,所以权限系统长期以来,很难界定数据权限的适用范围和如何建设一个通用的数据权限模型,所以实际过程中,我们看到所谓的通用的权限系统,都没有解决这部分问题,而具体的各个实际遇到该问题的系统的解决方案,更是千差万别。此外,很多系统都没能解决一个那就是如何通过权限反向查询人的问题,因为这个会带来更大的性能消耗。
建设一个仅仅只是满足鉴权目的权限系统并不复杂,复杂在于权限系统是企业管理的一部分,甚至是很关键的一部分,随着企业管理和运营要求的不同,权限系统所面临不仅仅是技术问题,而是如何管理的问题,不断演化的企业人员组织架构和业务条线,都对权限管理提出了新的诉求和差异化的要求,而且不断的有业务模型和超过经典权限模型的数据进入权限系统的范畴,都给权限系统的设计者们增添额不少的挑战。无论如何建设一个用户量少的权限系统是一个比较容易的事情且不用太担心性能的问题,如果建设一个满足十万级、百万级用户的权限系统,是一个极富挑战的工作。