- Spring Security
11个步骤为应用程序添加安全防护 - 历史与现状
自2003年出现的Spring扩展插件Acegi Security发展而来。
目前最新版本为3.x,已成为Spring的一部分。
为J2EE企业应用程序提供可靠的安全性服务。 - Authentication vs. Authorization
区分概念验证与授权
验证
这个用户是谁?
用户身份可靠吗?
授权
某用户A是否可以访问资源R
某用户A是否可以执行M操作
某用户A是否可以对资源R执行M操作 - SS中的验证特点
支持多种验证方式
支持多种加密格式
支持组件的扩展和替换
可以本地化输出信息 - SS中的授权特点
支持多种仲裁方式
支持组件的扩展和替换
支持对页面访问、方法访问、对象访问的授权。 - SS核心安全实现
Web安全
通过配置Servlet Filter激活SS中的过滤器链
实现Session一致性验证
实现免登陆验证(Remember-Me验证)
提供一系列标签库进行页面元素的安全控制
方法安全
通过AOP模式实现安全代理
Web安全与方法安全均可以使用表达式语言定义访问规则 - 配置SS
配置Web.xml,应用安全过滤器
配置Spring,验证与授权部分
在web页面中获取用户身份
在web页面中应用安全标签库
实现方法级安全 - 1:配置web.xml
Java代码- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter- class >org.springframework.web.filter.DelegatingFilterProxy</filter- class >
- </filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:spring.xml</param-value>
- </context-param>
- <listener>
- <listener- class >
- org.springframework.web.context.ContextLoaderListener
- </listener- class >
- </listener>
- 2:Spring配置文件中设置命名空间
Java代码- <?xml version= "1.0" encoding= "UTF-8" ?>
- <beans:beansxmlns= "http://www.springframework.org/schema/security"
- xmlns:beans= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http: //www.springframework.org/schema/beans
- http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http: //www.springframework.org/schema/security
- http: //www.springframework.org/schema/security/spring-security-3.0.xsd">
- </beans:beans>
- 3:配置最基本的验证与授权
Java代码- <http auto-config= "true" >
- <intercept-url pattern= "/**" access= "ROLE_USER" />
- </http>
- <authentication-manager>
- <authentication-provider>
- <user-service>
- <user name= "tom" password= "123" authorities= "ROLE_USER, ROLE_A" />
- <user name= "jerry" password= "123" authorities= "ROLE_USER, ROLE_B" />
- </user-service>
- </authentication-provider>
- </authentication-manager>
- 4:通过数据库验证用户身份
Java代码- <authentication-manager>
- <authentication-provider>
- <password-encoder hash=“md5”/>
- <jdbc-user-service data-source-ref= "dataSource" />
- </authentication-provider>
- </authentication-manager>
- 数据表结构见SS说明手册附录A
- 5:完善web页面验证规则
Java代码- <http auto-config= "true" >
- <intercept-url pattern= "/js/**" filters= "none" />
- <intercept-url pattern= "/css/**" filters= "none" />
- <intercept-url pattern= "/images/**" filters= "none" />
- <intercept-url pattern= "/a.jsp" access= "ROLE_A" />
- <intercept-url pattern= "/b.jsp" access= "ROLE_B" />
- <intercept-url pattern= "/c.jsp" access= "ROLE_A, ROLE_B" />
- <intercept-url pattern= "/**" access= "ROLE_USER" />
- </http>
- 6:自定义验证配置
Java代码- <http auto-config= "true" >
- <!-- 指定登陆页面、成功页面、失败页面-->
- <form-login login-page= "/login.jsp" default -target-url= "/index.jsp" authentication-failure-url= "/login.jsp" />
- <!-- 尝试访问没有权限的页面时跳转的页面 -->
- <access-denied-handler error-page= "/accessDenied.jsp" />
- <!-- 使用记住用户名、密码功能,指定数据源和加密的key -->
- <remember-me data-source-ref= "dataSource" />
- <!-- logout页面,logout后清除session -->
- <logout invalidate-session= "true" logout-success-url= "/login.jsp" />
- <!-- session 失效后跳转的页面,最大登陆次数 -->
- <session-management invalid-session-url= "/sessionTimeout.htm" >
- <concurrency-control max-sessions= "1" expired-url= "/sessionTimeout.htm" />
- </session-management>
- </http>
- 可以使用SS自带的登陆页面作为login.jsp的模板
- 7:本地化消息输出
拷贝本地化资源文件后,在配置文件中加载该文件:
Java代码- <!-- 加载错误信息资源文件 -->
- <beans:bean id= "messageSource"
- class = "org.springframework.context.support.ReloadableResourceBundleMessageSource" >
- <beans:property name= "basename" value= "classpath:messages" />
- </beans:bean>
- 资源文件在SS核心包:spring-security-core- 3.0 . 2 .RELEASE.jar的orgspringframeworksecurity目录中
- 8:在web页面中获取用户信息
Java代码- 方式一:Java代码
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- Collection<GrantedAuthority> col = auth.getAuthorities();
- 方式二:标签库
- <%@ taglib prefix= "sec" uri= "http://www.springframework.org/security/tags" %>
- <sec:authentication property="name“/>
- <sec:authentication property="authorities“/>
- 9:在web页面进行元素安全控制
Java代码- 方式一
- <sec:authorizeifAnyGranted= "ROLE_A" >
- <a href= "a.jsp" >你可以访问a.jsp</a>
- </sec:authorize>
- <sec:authorizeifNotGranted= "ROLE_A" >
- 你不可以访问a.jsp
- </sec:authorize>
- 方式二
- <sec:authorizeurl= "/a.jsp" >
- <a href= "a.jsp" >你可以访问a.jsp</a>
- </sec:authorize>
- 10:全局方法安全控制
Java代码- <global-method-security pre-post-annotations= "enabled" >
- <protect-pointcut expression= "execution(* com.xasxt.*Service.add*(..))" access= "ROLE_A" />
- <protect-pointcut expression= "execution(* com.xasxt.*Service.delete*(..))" access= "ROLE_B" />
- </global-method-security>
- 此处使用了AspectJ中常用的切入点表达式(百度:AspectJ execution)
- 11:使用注解进行方法安全控制
Java代码- public class DemoService {
- @PreAuthorize ( "hasRole('ROLE_A')" )
- public void methodA() {
- }
- @PreAuthorize ( "hasAnyRole('ROLE_A, ROLE_B')" )
- public void methodB() {
- }
- }
- hasRole与hasAnyRole为SS通用内置表达式(google : spring security Common Built-In Expressions)
- 12:下一步做什么???
采用更安全的验证方式
采用安全的数据传输方式
实现动态授权
自定义验证与授权部件
实现数据级安全