Spring

Spring Security 优劣

 

拜读了 Spring Security 相关帖子和 Spring Security 参考文档。现将我理解的 Spring Security 写下来和大家共享。

 

本文目的是从 Spring Security 能够提供的功能、以及基本原理角度分析,并不深入到如何编码。然后反过来,审查我们的软件系统需要哪些权限控制。进而评审 Spring Security 的适用性。

 

本文力求文字简单,概念也简单。

--------------------------------------------------------------

文章大纲:

Spring Security 如何控制权限

    概要

    与WEB系统的集成
    控制内容
    细粒度权限控制
我们理想中的权限管理
    客户对权限管理的需求
    开发中遇到的难点
    我们理想的权限管理
Spring Security的评价
    优点
    缺点

--------------------------------------------------------------

Spring Security 如何控制权限

概要

Spring 使用由 Filter 组成的 Chain ,来判断权限。如下图所示:

 

Spring 预定义了很多 out-of-boxed filter 供开发者直接使用。

每个 Filter 一般情况下(有些 Filterabstract 的),都和配置文件的一个元素(有的情况下可能是属性)对应。

比如: AUTHENTICATION_PROCESSING_FILTER ,对应配置文件里面的: http/form-login 元素。

 

如果 Spring 提供的 Filter 不能满足系统的权限功能,开发者可以自定义 Filter ,然后把 Filter 放在某个 Filter Chain 的某个位置。可以替换掉原有 Filter Chain 的某个 Filter ,也可以放在某个 Filter 之前或者之后。

 

总之, Spring Security 采用 Filter Chain 模式判断权限, Spring 提供了一些 Filter ,也支持开发者自定义 Filter

WEB 系统的集成

使用 Java EEFilter (非 SpringFilter )机制,将需要权限判断的 url ,“牵引”给 SpringFilter Chain 即可。

 

一般情况下,将所有的 url 都引入 Filter Chain 。当然也可以在 web.xml 配置需要权限判断的 url (配置 filter-mapping/url-pattern )。 Spring 的配置文件也支持过滤掉不需要权限判断的 url (配置 http/intercept-url 元素)。

控制内容

Spring Security 提供了如下内容的控制:

1.       url

2.       bean method

3.       http session

 

url :可以分为需要权限判断的 url ,不需要权限判断的 url ,登录表单 url 。通过我对 spring 相关帖子和参考文档的阅读,需要权限判断的 url 。仅限于做角色判断,就是说判断当前用户是否具有指定的角色。

 

bean methodSpring 支持对 Service layer method 做权限判断。通过我对 spring 相关帖子和参考文档的阅读,也仅限于做角色判断。配置方式有 2 种:

1.       写在 Java 源代码里面,如: @Secured("ROLE_TELLER") (该方法只有具有 TELLER 角色的用户能够访问,否则抛出异常);

2.       写在配置文件里面,如: <protect method="set*" access="ROLE_ADMIN" /> (该 bean 的所有 set 方法,只有具有 ADMIN 角色的用户能够访问,否则抛出异常)。

 

http session :控制一个用户名是否能重复登录,以及重复登录次数,并非重试密码次数。

 

另外, Spring Security 还提供了如下一些功能:

1.       remember me ,记住我;

2.       form-login 登录控制;

3.       多种身份认证功能;

4.       用户密码加密和“ salt ”功能;

5.       http 协议控制;

6.       访问端口控制;

7.       Pre-Invocation & After-Invocation

 

remember me ,记住我:还记得浏览器采用 cookie 记住用户名和密码自动登录吗?好像就是这个(不知道我理解错了没有,应该没有。只是我不大敢相信)。使用这个功能,开发者在登录页面,使用 spring 自定义的标签。

 

form-login 登录控制:有些页面不允许匿名访问,那么当匿名访问这些页面的时候,将弹出(或者转到) form-login 窗口(或者页面)。这里又牵引出 2 个问题: 1 ,输入用户名和密码后怎样验证; 2 ,密码是否需要加密,怎么加密。

 

多种身份认证功能: Spring 提供了丰富的用户身份认证功能。身份认证是什么意思?比如您告诉我“我是神仙”。那么我会问您“凭什么证明您是神仙”。这就是身份认证。认证手段一般是保存到数据库表的用户名 / 密码, usb keyldap 等。一般情况下,我们都使用用户名 / 密码的。

 

用户密码加密和“ salt ”功能:密码采用 md5 ,还是 sha 加密算法。如果我们对密码加密的时候,不想仅仅对密码加密,还想把用户名和密码放在一起加密做为加密后的密码。那么使用 salt 吧。 salt 支持也读取用户的其他属性,不仅是用户名。

 

http 协议控制:哪些 url ,必须采用 https 访问呢?哪些 url 必须采用 http 访问呢?哪些又两者都可以呢?通过这个配置。

 

访问端口控制:类似 http 协议控制,控制 url 和访问端口之间的关系。

 

Pre-Invocation & After-Invocation :在方法调用之前做权限判断,还是方法调用之后做权限判断呢?一般情况下是之前调用。也有情况下是之后调用。具体例子可以看官方文档( 22.3 小节)。

细粒度权限控制

由上面分析,我们看到 urlmethod 的权限判断,都仅限于用户角色权限判断。事实上 Spring 使用投票( Voter )机制,来做权限判断。用户角色权限也是一种投票。

投票这个词,听起来不容易懂。举例:董事会开会,各个股东投票以表决决议是否通过。 Spring 的角色投票器,只会投出一票。我们平时所说的投票至少要 2 张票吧,一张还叫什么投票。 Spring 的投票有 3 种结果:允许、拒绝和弃权。弃权?真的有点晕。呵呵,这种情况下还弃权。

 

那么投票器,如何集成到 SpringFilter 里面呢?

SpringFilter 一般都由一个 Manager 支撑着。比如 accessDecisionManager ,可以由 RoleVoterBasicAclEntryVoter 提供投票。 accessDecisionManager 根据 RoleVoterBasicAclEntryVoter 投票结果,做出决策判断。

 

细粒度(数据级)的权限控制, Spring Security 提供了一种模型以及相关实现。下面我简要说说这个模型。

举例:张三授权查询华北区域客户资料,李四授权查询华南区域客户资料。那么,首先会对所有客户记录做个标示(相当于取个 id ),然后在 acl-entry 表给张三授权华北所有客户访问权限;给李四华南区域所有客户权限。表记录大致是这样的:

访问用户

被访问数据

授权操作

张三

华北电力客户 1

读取

张三

华北电力客户 2

读取

李四

华南电力客户 1

读取

这个模型的缺点是非常明显的:

1.       和业务数据绑定死了,业务数据的增 / 删,需要维护该权限表;

2.       在大数据量的情况下,系统效率低下。

 

因此,开发者需要自己书写投票器了。

我们理想中的权限管理

客户对权限管理的需求

这里是指我们服务的最终用户,而不是软件开发者。客户对权限管理的需求,大体可以概括如下:

1.       自主灵活地管理角色、角色权限,并将角色赋予系统相关用户;

2.       数据安全。系统展现数据是满足权限的,在系统内部搜索数据也必须在相应权限访问内,对系统数据进行增加、修改、删除必须是满足权限的;

3.       没有功能的按钮、菜单、数据等等,就不要在界面上出现了。

开发中遇到的难点

管理用户、角色、权限,以及三者之间的关系,这种典型的 RBAC 模型,非常容易,没有任何困难。

 

困难的是,数据级权限控制。这是和业务直接挂钩的,最复杂,而且会经常因为客户需求表达不到位、开发人员需求理解不到位、系统框架库表结构发生变化,而不断变化的。

这种变化,不仅需要编码,而且还需要重新测试。甚至这种变化会波及到其他模块,甚至整个系统。

系统开发经历几次变化下来,代码里面散布着 if/else ,散布着 sql 语句。导致 bad smell

我们理想的权限管理

我们期望的权限管理,应该具有这么几个特性:

1.       能实现角色级权限;能实现数据级权限;

2.       简单、易操作,能够应对各种需求;

3.       应对需求变更能力强;

4.       最好有相关界面,比如权限管理界面、角色管理界面,角色和权限关系维护界面,用户和角色关系维护界面。如果没有界面,也是可以接受的。毕竟这些页面需要最终用户来使用,不同用户对系统的界面要求不同。因此我们并不期望统一的管理界面。

 

Spring Security 的评价

Spring Security 世界里,可以区分出哪些资源可以匿名访问,哪些需要角色权限,又是哪个页面提供登录功能;怎样进行用户身份认证,用户的密码如何加密。哪些资源必须使用 https 协议,资源和访问端口有怎样的对应关系。

 

下面就优点和缺点对 Spring Security 进行点评。

优点

总体说来 Spring Security 具有以下几个优点:

1.       提供了一套权限框架,这套框架是可行的;

2.       提供了很多用户身份认证功能,可以节约大量开发工作;

3.       提供了角色判断功能,这点既是优点又是缺点;

4.       提供了 form-loginremember me 等控制。

 

其中 24 两点,对于我们中国开发者(我对国外系统不大了解),可用性并不大。我们的系统大多采用用户名 / 密码身份认证模式,大多公司都有可复用代码。 form-loginremember me 等这些功能,并不是难以开发,而且可用之处也并不多。

缺点

我个人认为 Spring Security 存在以下几个硬伤:

1.       角色被“编码”到配置文件和源文件,这样最终用户就不能创建角色了。但最终用户期望自己来控制角色。因为在项目实施过程中,客户可能并不能确定有哪些角色,以及角色怎么分配给系统用户。角色大多需要等到系统上线后,才能确定。这些编码有:

a)      url 的权限控制, <intercept-url pattern="/**" access="ROLE_USER" />

b)      java 方法的权限控制, @Secured("IS_AUTHENTICATED_ANONYMOUSLY")

c)       java 方法的权限控制, <protect method="set*" access="ROLE_ADMIN" />

2.       RBCA 这种被广泛运用的模型,没有在 Spring Security 体现出来;

3.       Spring Security 没有提供好的细粒度(数据级)权限方案,提供的缺省实现维护工作量大,在大数据量情况下,几乎不可用;

4.       Spring Security 对于用户、角色、权限之间的关系,没有提供任何一种维护界面。不过从 Spring Security 角度看,确实没有必要有界面。角色创建、角色和权限直接的关系,都被“编码”到配置文件和源文件了;

5.       Spring Security 学习难度大,配置文件还是很多。我承认有很多高手,但我们也看到有很多新人加入软件开发领域。付出如此大的学习代价,获得这么一点点好处,个人觉得并不值得。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值