董一璠,李宝林,何先波
(西华师范大学 计算机学院,四川 南充 637000)
联通资源管理系统是由四川南充联通公司授权,由我处完成的一个对联通本地资源的管理系统。管理的资源包括各类通信设备、机房或节点、杆线资源、管孔资源及客户信息等。本软件主要用于完成联通南充公司的各类资源的录入、浏览、查询、统计等功能,拟采用文字表格、逻辑图及GIS等多种方式实现对各类资源的操作和管理。开发过程中发现由于各个不同部门之间需要管理的业务模块不尽相同,互相之间既需要连通性,有需要隔离性。所以对于联通资源管理系统的权限授予和权限验证提出了极大地要求。本系统采用面向对象的J2EE进行开发,系统是典型的B/S结构。所以我们采用Spring Security安全框架对整个系统的安全框架进行搭建,采用严格的权限控制和角色化的操作界面实现整个系统的安全性和操作界面的简洁性。既很好的解决了系统权限控制问题,而且安全可靠,便于移植重利用。
在基于B/S结构的J2EE企业级应用系统中,客户登陆认证、访问授权控制是重要组成部分,Spring Security提供了一个较成熟的安全框架[1]。
Spring Security是由Acegi Security发展而来的,是Spring框架的组成部分,Spring Security框架主要提供“认证”和“授权访问”,“认证”为用户建立一个他所需要声明的主题,即用户或在你系统中执行的其他设备或系统。另一个是“授权”,授权是指已经提前建立好了某个用户被授予的权利,能否执行某个操作,在执行之前就已经进行了授权判断。Spring Security也支持大量的第三方验证模型[2]。
Spring Security通过使用Servlet过滤器对Web安全性进行支持,过滤器过滤Servlet的访问请求,将这些请求转发给认证授权管理决策处理器进行安全处理,从而曾强了系统的访问安全性。每一个请求发出后,至少要经过以下4个过滤器,如图1所示。
图1 四重安全过滤器结构Fig.1 Four security filters structure
1)集成过滤器:负责在请求刚发出的时候检验是否在HTTP会话中已经存储了一个用户的验证信息,为其他过滤器的处理做准备。
2)认证处理过滤器:负责判断是否为一个认证请求。如果是,相关的认证信息会从中提取出来,然后转移给认证管理器进行处理,确定这个用户的身份。如果不是,认证处理过滤器不做任何处理,该请求继续前进。
3)例外转换过滤器:负责将可能被抛出的异常“Access Denied Exception”和 “Authentication Exception”转化为对应的HTTP响应。
4)过滤器安全拦截器:负责Web应用程序的安全拦截。检查请求中的用户是否是具有访问被保护资源的的权限的用户。它的工作依赖于认证管理器和访问决策管理器[3]。
为了使用Spring Security框架,在WEB项目的web.xml中需作如下配置:
其中springSecurityFilterChain过滤器是Spring Security框架的总体配置,applicationContext*.xml是对所有Spring配置文件导入的配置。Spring Security的配置文件名为applicationcontext-security.xml。
在联通资源管理系统中,因为用户量大,所以用户需要用数据库中的表进行保存。表中的用户和密码信息的查询信息通过UserService实现。我们的系统中UserService实现用户认证(authentiation)和资源访问授权(Authorization)的相关基本操作,其中包括用户和密码的添加、删除、更改和查询。在实现中,UserService需实现UserDetailsService接口,该接口也是spring认证框架要求实现的。UserDetailsService接口只包 含 一 个 方 法 :UserDetails loadUserByUsername (String username)。该方法通过用户名去查询用户相关的详细信息,返回实现UserDetails接口的类,对框架来说,其操作主要通过UserDetailsService和UserDetails实现。在我们的项目中使用类UserDetailsImpl类实现接口UserDetails, 如下是
在UserDetailsImpl中定义了一个很重要的Java Bean——uservo。在我们的项目中,User为PO对象,与数据库中的表user的记录对应。UserVO为VO对象,根据业务逻辑进行加工:
在UserService实现类中,通过public void init(){umapper=session.getMapper(UserMapper.class); } 实现与数据库表及基本操作的关联,UserMapper为CRUD操作实现接口,框架会自动实现相关类的实例化 (UserMapper.xml在mybatis配置文件中引用,UserExample与User类会在UserMapper接口框架实现中引用,框架可采用动态代理等技术得到类实例).UserVO除了包括User的信息以外,还须对User信息进一步细化,如GroupId到Group类实例,另外,授权部分,我们的系统并未在库中实现,而是嵌在代码中,故需找到该部分内容。这些主要在如下调用中实现(由convert2vo完 成 ):UserDetails ud= new UserDetailsImpl (convert2vo(user));由此可知,认证的基本思想及调用实现如下:
1)org.springframework.security.core.context.SecurityContext接口表示的是当前应用的安全上下文。通过此接口可以获取和设置当前的认证对象。org.springframework.security.core.Authentication接口用来表示此认证对象。通过认证对象的方法可以判断当前用户是否已经通过认证,以及获取当前认证用户的相关信息,包括用户名、密码和权限等。
2)要使用此认证对象,首先需要获取到 Security Context对象。通过 org.springframework.security.core.context.Security Context Holder类提供的静态方法 getContext()就可以获取。
3)通过 SecurityContext对象的 getAuthentication()方法可以得到认证对象。通过认证对象的 getPrincipal()方法就可以获得当前的认证主体,通常是UserDetails接口的实现。
4)典型的认证过程就是当用户输入了用户名和密码之后,UserDetailsService通过用户名找到对应的UserDetails对象,接着比较密码是否匹配。如果不匹配,则返回出错信息;如果匹配的话,说明用户认证成功,就创建一个实现了Authentication接口的对象,如 org.springframework.security.authentication.Username Password AuthenticationToken类的对象。再通过SecurityContext的setAuthentication()方法来设置此认证对象。
综上所述,整个登录过程如图2所示。
图2 登陆安全验证结构Fig.2 Login Security verification structure
系统要首先根据需要定义好角色,并为每一角色分配合适的访问权限,然后再根据用户的职责和权利指派不同的角色。这样就实现了权限和用户的逻辑分离,使得权限分配的灵活性问题得以解决。在联通资源管理系统中,我们也是按照联通公司对企业人员的分组对角色进行分配的,对于每个模块都要有相应的读(R)写(W)查(S)权限的管理。不同分组用户对不同模块具有不同的权限,需要分别授予,如图3所示。
图3 权限控制结构Fig.3 Authority manage structure
系统的角色通过枚举RoleEnum实现,这也是用户管理权限设置部分的信息来源:
授权是以组的方式存在,故一个Authority有组标识,其权限由其分配的角色而定,一个组可能对应多个Authority。
系统用户的权限获取在UserService.getAuthorities方法中实现,根据枚举内容赋予所有权限(读、写和执行),代码如下:
一般用户的权限则通过组 AuthorityService.getAuthoritiesByGroupId方法实现,在authority表中内容如图4所示。
图4 用户组权限表Fig.4 User group permissions list
在spring安全机制中,有大量的如下配置:
特别是在applicationContext-security.xml中。这是在配置文件中集中配置允许登入的权限。该方式主要针对URL地址及参数过滤,主要用于控制网页整体的访问,可在实现中对各网页名字和存储路径进行合理规划达到安全控制的目的。另外,也可通过struts配置实现对方法访问的控制,但struts配置较庞大。还有一种方式,是通过jsp的安全按标签实现对网页元素的显示控制,例如
authorize标签用来决定它的内容是否会被执行,另外,<sec:authentication?标签用于访问当前的Authentication对象,保存在安全上下文中。
通过UserDetails接口中的getAuthorities()方法实现的,该方法返回一权限名字字符串集合。本系统的具体实现如下:
上面代码中,GrantedAuthorityImpl包含了字符串名(role字符串成员变量),并实现了GrantedAuthority接口。综上可知,UserService实现了框架所需的所有操作,UserVO包含了安全相关的所有信息,UserDetailsImpl实现了框架所需要的接口。
在基于J2EE的企业级B/S项目中,安全是一个自发展开始以来一直非常受到重视的内容。在系统的开发过程中,对于代码的复用率,可移植性等问题,一直是程序开发人员的头等大事。而Spring Security为我们提供了一个十分便利有效的管理模块。通过对端口的加载,和对拦截器与权限的配置,可以让你的系统在很短的时间内,就拥有一个良好的安全机制。在使用过程中发现的问题如下:
1)由于采用将用户信息保存在session中,当修改或更新了用户信息后,无法立刻将新的用户信息用于当前用户。实时更新用户信息,是目前Spring Security的一个大问题[4]。
2)应该考虑如何引入spring AOP对方法进行控制。
[1]蒲子明,许勇,王黎.Struct+Hibernate+Spring整合开发技术详解[M].北京:清华大学出版社,2010.
[2]佚名.Spring安全框架 [EB/OL].[2012-11-18]http://www.oschina.net/p/spring+security.
[3]佚名.Spring Security介绍 (4)[EB/OL].[2012-11-18]http://www.4ucode.com/study/topic/353380.
[4]马楠.基于Spring的J2EE安全框架的研究与应用[D].北京:北京邮电大学,2009.
[5]丁振凡.基于Spring Security的Web资源访问控制[J].宜春学院学报,2012(8):36-1250.DING Zhen-fan.Access control for web resources based on spring security[J].Journal of Yichun University,2012(8):36-1250.
[6]熊昊.基于Spring的Acegi安全框架及其应用研究[D].长沙:国防科学技术大学,2008.