http://www.iteye.com/topic/259816
Spring Security优劣之我见
拜读了Spring Security相关帖子和Spring Security参考文档。现将我理解的Spring Security写下来和大家共享。
本文目的是从Spring Security能够提供的功能、以及基本原理角度分析,并不深入到如何编码。然后反过来,审查我们的软件系统需要哪些权限控制。进而评审Spring Security的适用性。
本文力求文字简单,概念也简单。
--------------------------------------------------------------
文章大纲:
Spring Security 如何控制权限
概要
与WEB系统的集成
控制内容
细粒度权限控制
我们理想中的权限管理
客户对权限管理的需求
开发中遇到的难点
我们理想的权限管理
Spring Security的评价
优点
缺点
--------------------------------------------------------------
Spring Security如何控制权限
概要
Spring使用由Filter组成的Chain,来判断权限。如下图所示:
<!--[if !vml]--><!--[endif]-->[/img]
Spring预定义了很多out-of-boxed filter供开发者直接使用。
每个Filter一般情况下(有些Filter是abstract的),都和配置文件的一个元素(有的情况下可能是属性)对应。
比如: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 EE的Filter(非Spring的Filter)机制,将需要权限判断的url,“牵引”给Spring的Filter Chain即可。
一般情况下,将所有的url都引入Filter Chain。当然也可以在web.xml配置需要权限判断的url(配置filter-mapping/url-pattern)。Spring的配置文件也支持过滤掉不需要权限判断的url(配置http/intercept-url元素)。
控制内容
Spring Security提供了如下内容的控制:
<!--[if !supportLists]-->1. <!--[endif]-->url;
<!--[if !supportLists]-->2. <!--[endif]-->bean method;
<!--[if !supportLists]-->3. <!--[endif]-->http session。
url:可以分为需要权限判断的url,不需要权限判断的url,登录表单url。通过我对spring相关帖子和参考文档的阅读,需要权限判断的url。仅限于做角色判断,就是说判断当前用户是否具有指定的角色。
bean method:Spring支持对Service layer method做权限判断。通过我对spring相关帖子和参考文档的阅读,也仅限于做角色判断。配置方式有2种:
<!--[if !supportLists]-->1. <!--[endif]-->写在Java源代码里面,如:@Secured("ROLE_TELLER")(该方法只有具有TELLER角色的用户能够访问,否则抛出异常);
<!--[if !supportLists]-->2. <!--[endif]-->写在配置文件里面,如:<protect method="set*" access="ROLE_ADMIN" />(该bean的所有set方法,只有具有ADMIN角色的用户能够访问,否则抛出异常)。
http session:控制一个用户名是否能重复登录,以及重复登录次数,并非重试密码次数。
另外,Spring Security还提供了如下一些功能:
<!--[if !supportLists]-->1. <!--[endif]-->remember me,记住我;
<!--[if !supportLists]-->2. <!--[endif]-->form-login登录控制;
<!--[if !supportLists]-->3. <!--[endif]-->多种身份认证功能;
<!--[if !supportLists]-->4. <!--[endif]-->用户密码加密和“salt”功能;
<!--[if !supportLists]-->5. <!--[endif]-->http协议控制;
<!--[if !supportLists]-->6. <!--[endif]-->访问端口控制;
<!--[if !supportLists]-->7. <!--[endif]-->Pre-Invocation & After-Invocation。
remember me,记住我:还记得浏览器采用cookie记住用户名和密码自动登录吗?好像就是这个(不知道我理解错了没有,应该没有。只是我不大敢相信)。使用这个功能,开发者在登录页面,使用spring自定义的标签。
form-login登录控制:有些页面不允许匿名访问,那么当匿名访问这些页面的时候,将弹出(或者转到)form-login窗口(或者页面)。这里又牵引出2个问题:1,输入用户名和密码后怎样验证;2,密码是否需要加密,怎么加密。
多种身份认证功能:Spring提供了丰富的用户身份认证功能。身份认证是什么意思?比如您告诉我“我是神仙”。那么我会问您“凭什么证明您是神仙”。这就是身份认证。认证手段一般是保存到数据库表的用户名/密码,usb key,ldap等。一般情况下,我们都使用用户名/密码的。
用户密码加密和“salt”功能:密码采用md5,还是sha加密算法。如果我们对密码加密的时候,不想仅仅对密码加密,还想把用户名和密码放在一起加密做为加密后的密码。那么使用salt吧。salt支持也读取用户的其他属性,不仅是用户名。
http协议控制:哪些url,必须采用https访问呢?哪些url必须采用http访问呢?哪些又两者都可以呢?通过这个配置。
访问端口控制:类似http协议控制,控制url和访问端口之间的关系。
Pre-Invocation & After-Invocation:在方法调用之前做权限判断,还是方法调用之后做权限判断呢?一般情况下是之前调用。也有情况下是之后调用。具体例子可以看官方文档(22.3小节)。
细粒度权限控制
由上面分析,我们看到url、method的权限判断,都仅限于用户角色权限判断。事实上Spring使用投票(Voter)机制,来做权限判断。用户角色权限也是一种投票。
投票这个词,听起来不容易懂。举例:董事会开会,各个股东投票以表决决议是否通过。Spring的角色投票器,只会投出一票。我们平时所说的投票至少要2张票吧,一张还叫什么投票。Spring的投票有3种结果:允许、拒绝和弃权。弃权?真的有点晕。呵呵,这种情况下还弃权。
那么投票器,如何集成到Spring的Filter里面呢?
Spring的Filter一般都由一个Manager支撑着。比如accessDecisionManager,可以由RoleVoter和BasicAclEntryVoter提供投票。accessDecisionManager根据RoleVoter,BasicAclEntryVoter投票结果,做出决策判断。
细粒度(数据级)的权限控制,Spring Security提供了一种模型以及相关实现。下面我简要说说这个模型。
举例:张三授权查询华北区域客户资料,李四授权查询华南区域客户资料。那么,首先会对所有客户记录做个标示(相当于取个id),然后在acl-entry表给张三授权华北所有客户访问权限;给李四华南区域所有客户权限。表记录大致是这样的:
访问用户
被访问数据
授权操作
张三
华北电力客户1
读取
张三
华北电力客户2
读取
李四
华南电力客户1
读取
…
…
…
这个模型的缺点是非常明显的:
<!--[if !supportLists]-->1. <!--[endif]-->和业务数据绑定死了,业务数据的增/删,需要维护该权限表;
<!--[if !supportLists]-->2. <!--[endif]-->在大数据量的情况下,系统效率低下。
因此,开发者需要自己书写投票器了。
我们理想中的权限管理
客户对权限管理的需求
这里是指我们服务的最终用户,而不是软件开发者。客户对权限管理的需求,大体可以概括如下:
<!--[if !supportLists]-->1. <!--[endif]-->自主灵活地管理角色、角色权限,并将角色赋予系统相关用户;
<!--[if !supportLists]-->2. <!--[endif]-->数据安全。系统展现数据是满足权限的,在系统内部搜索数据也必须在相应权限访问内,对系统数据进行增加、修改、删除必须是满足权限的;
<!--[if !supportLists]-->3. <!--[endif]-->没有功能的按钮、菜单、数据等等,就不要在界面上出现了。
开发中遇到的难点
管理用户、角色、权限,以及三者之间的关系,这种典型的RBAC模型,非常容易,没有任何困难。
困难的是,数据级权限控制。这是和业务直接挂钩的,最复杂,而且会经常因为客户需求表达不到位、开发人员需求理解不到位、系统框架库表结构发生变化,而不断变化的。
这种变化,不仅需要编码,而且还需要重新测试。甚至这种变化会波及到其他模块,甚至整个系统。
系统开发经历几次变化下来,代码里面散布着if/else,散布着sql语句。导致bad smell。
我们理想的权限管理
我们期望的权限管理,应该具有这么几个特性:
<!--[if !supportLists]-->1. <!--[endif]-->能实现角色级权限;能实现数据级权限;
<!--[if !supportLists]-->2. <!--[endif]-->简单、易操作,能够应对各种需求;
<!--[if !supportLists]-->3. <!--[endif]-->应对需求变更能力强;
<!--[if !supportLists]-->4. <!--[endif]-->最好有相关界面,比如权限管理界面、角色管理界面,角色和权限关系维护界面,用户和角色关系维护界面。如果没有界面,也是可以接受的。毕竟这些页面需要最终用户来使用,不同用户对系统的界面要求不同。因此我们并不期望统一的管理界面。
Spring Security的评价
在Spring Security世界里,可以区分出哪些资源可以匿名访问,哪些需要角色权限,又是哪个页面提供登录功能;怎样进行用户身份认证,用户的密码如何加密。哪些资源必须使用https协议,资源和访问端口有怎样的对应关系。
下面就优点和缺点对Spring Security进行点评。
优点
总体说来Spring Security具有以下几个优点:
<!--[if !supportLists]-->1. <!--[endif]-->提供了一套权限框架,这套框架是可行的;
<!--[if !supportLists]-->2. <!--[endif]-->提供了很多用户身份认证功能,可以节约大量开发工作;
<!--[if !supportLists]-->3. <!--[endif]-->提供了角色判断功能,这点既是优点又是缺点;
<!--[if !supportLists]-->4. <!--[endif]-->提供了form-login、remember me等控制。
其中2、4两点,对于我们中国开发者(我对国外系统不大了解),可用性并不大。我们的系统大多采用用户名/密码身份认证模式,大多公司都有可复用代码。form-login、remember me等这些功能,并不是难以开发,而且可用之处也并不多。
缺点
我个人认为Spring Security存在以下几个硬伤:
<!--[if !supportLists]-->1. <!--[endif]-->角色被“编码”到配置文件和源文件,这样最终用户就不能创建角色了。但最终用户期望自己来控制角色。因为在项目实施过程中,客户可能并不能确定有哪些角色,以及角色怎么分配给系统用户。角色大多需要等到系统上线后,才能确定。这些编码有:
<!--[if !supportLists]-->a) <!--[endif]-->url的权限控制,<intercept-url pattern="/**" access="ROLE_USER" />;
<!--[if !supportLists]-->b) <!--[endif]-->java方法的权限控制,@Secured("IS_AUTHENTICATED_ANONYMOUSLY");
<!--[if !supportLists]-->c) <!--[endif]-->java方法的权限控制,<protect method="set*" access="ROLE_ADMIN" />;
<!--[if !supportLists]-->2. <!--[endif]-->RBCA这种被广泛运用的模型,没有在Spring Security体现出来;
<!--[if !supportLists]-->3. <!--[endif]-->Spring Security没有提供好的细粒度(数据级)权限方案,提供的缺省实现维护工作量大,在大数据量情况下,几乎不可用;
<!--[if !supportLists]-->4. <!--[endif]-->Spring Security对于用户、角色、权限之间的关系,没有提供任何一种维护界面。不过从Spring Security角度看,确实没有必要有界面。角色创建、角色和权限直接的关系,都被“编码”到配置文件和源文件了;
<!--[if !supportLists]-->5. <!--[endif]-->Spring Security学习难度大,配置文件还是很多。我承认有很多高手,但我们也看到有很多新人加入软件开发领域。付出如此大的学习代价,获得这么一点点好处,个人觉得并不值得。
附言:
本人在JavaEye创建“权限管理”圈子快2周了,吸引不少网友进来。我感到很高兴,也很荣幸。由于Spring Security运用范围还是比较广的,所以我打算好好学习一下,把学习经验和大家分享一下。
欢迎大家加入“权限管理”圈子讨论,探讨对权限管理的认识、看法、建议等等。
http://accessmanager.group.iteye.com/
分享到:
相关推荐
Spring Boot 连接 Oracle 数据库 JDBC 配置步骤 在本文中,我们将详细介绍如何使用 Spring Boot 连接 Oracle 数据库,配置 JDBC 驱动程序,并实现数据库的基本操作。 Step 1: 添加依赖项 在 Spring Boot 项目中,...
下面将详细阐述如何进行Spring Security的数据库权限管理配置。 1. **配置数据源** 在Spring Security中,我们需要一个数据源来连接到数据库,存储用户、角色和权限信息。在Spring Boot项目中,可以通过...
- **配置数据源**:首先需要配置数据源,以便Spring能够访问数据库。 - **配置事务管理器**:接下来,需要配置一个事务管理器(如`DataSourceTransactionManager`),它负责管理事务的开始、提交和回滚。 - **配置...
Spring综合实例 spring配置oracel数据库 事务管理 切面 业务描述:实现用户简单的注册登录功能。 用户注册时候需要输入用户名,密码,邮箱地址,点击注册后成功。 用户登录时可以选择使用用户名或者邮箱地址进行...
本文将详细探讨"Spring数据库连接等配置加密"这一主题。 首先,我们来看`dbconfig.properties`文件,这是Spring项目中常见的用于存储数据库连接配置的文件。通常,这个文件会包含如下内容: ``` # 数据库连接配置 ...
在 `springBatchDemo` 文件中,通常包含了示例代码,演示如何配置和运行一个简单的Spring Batch作业,涉及到读取数据库中的数据,进行处理,然后写回到数据库。你可以参考这些代码,理解Spring Batch的工作原理和...
本文将详细介绍如何在Spring框架中配置数据库连接,包括使用JDBC、JPA、Hibernate等技术,以及如何利用Spring Boot的自动配置功能简化配置过程。 在Spring框架中配置数据库连接是一个基础而重要的任务。通过本文的...
本文将详细讲解如何使用 Spring 连接数据库,包括创建数据库、配置 Spring、编写数据库操作代码等步骤。 创建数据库 首先,我们需要创建一个数据库。这里,我们使用 MySQL 数据库管理系统和 SQLyog 工具来创建一个...
可以通过Spring Security来控制用户的数据库访问权限,防止未经授权的数据库操作。 9. **测试与监控**:在开发和运行阶段,对多数据源的测试和监控同样重要。使用像Spring Boot Actuator这样的工具,可以实时监控...
spring配置数据库文件,连接数据库的一写配置文件
项目自身的权限信息结合spring security 框架的实现。 本DEMO只包括从数据库读取登录认证信息,认证通过后 从数据库读取授权信息来控制用户的访问.权限元素包括 用户,角色,菜单以及这三者的关系。 本DEMO使用了...
很好的spring+ibatis事务的配置文档.
spring mvc jdbc 连接数据库配置说明
在这个简单的例子中,我们将探讨如何利用Spring Security与数据库进行交互来实现用户认证和授权。 首先,`applicationContext-security.xml`是Spring Security的配置文件,它定义了安全相关的bean和规则。这个文件...
在Spring中配置数据库连接池,通常需要在配置文件(如`applicationContext.xml`)中添加相应的bean定义。例如,如果使用HikariCP,配置如下: ```xml ``` 在上述配置中,我们指定了数据源类型...
总结来说,这个"spring连接数据库实例"主要涵盖了Spring框架中`DataSource`的配置、`JdbcTemplate`的使用以及事务管理的实现。通过这些知识点,我们可以高效地在Spring应用中实现与数据库的交互,提高开发效率。在...
本篇文章将详细讲解如何在SpringCloud项目中配置Oracle数据库,并从数据库中获取数据。 首先,我们需要在项目中引入SpringBoot对Oracle数据库的支持。这可以通过在`pom.xml`文件中添加相应的依赖来实现。通常,你...
在Spring Boot应用中,我们可以利用其强大的自动化配置和Spring Task模块来实现基于数据库配置的定时任务。Spring Task是Spring框架的一部分,它提供了丰富的定时和调度功能,使得在Java应用中执行周期性任务变得...
此外,Spring Data JPA和MyBatis等持久层框架也支持多数据库配置。它们通常需要额外的配置来指定使用的`DataSource`,并通过`@Repository`或`@Mapper`注解的子类来区分不同数据库的操作。 最后,为了确保事务的一致...
本文将深入探讨Spring JDBC在数据库配置加密方面的重要性和实践方法。 首先,理解Spring JDBC的基础知识至关重要。Spring JDBC通过JdbcTemplate和NamedParameterJdbcTemplate等类,封装了数据库连接、SQL执行和结果...