《SpringSecurity培训.ppt》由会员分享,可在线阅读,更多相关《SpringSecurity培训.ppt(37页珍藏版)》请在三一办公上搜索。
1、Spring Security,主讲:柴炎星2011-03-28,流程介绍,Spring Security 简介Spring Security 11种过滤器介绍Spring Security 基本配置Spring Security 总结,Spring Security 简介,这里提到的Spring Security也就是被大家广为熟悉的Acegi Security,2007年底Acegi Security正式成为Spring Portfolio项目,并更名为Spring Security。Spring Security是一个能够为基于Spring的企业应用系统提供描述性安全访问控制解决方案的安
2、全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC(依赖注入,也称控制反转)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。,如今的Spring Security已经成为Spring Framework下最成熟的安全系统,它为我们提供了强大而灵活的企业级安全服务,如:认证授权机制 Web资源访问控制 业务方法调用访问控制 领域对象访问控制Access Control List(ACL)单点登录(Central Authentication Service)X509认证 信道安全(
3、Channel Security)管理等功能 当保护Web资源时,Spring Security使用Servlet 过滤器来拦截Http请求进行身份验证并强制安全性,以确保WEB资源被安全的访问。,无论是保护WEB资源还是保护业务方法或者领域对象,Spring Security都是通过上图中的组件来完成的。本文主要阐述如何使用Spring Security对WEB应用程序的资源进行安全访问控制,并通过一个简单的实例来对Spring Security提供的各种过滤器的功能和配置方法进行描述。,Spring Security 11种过滤器介绍,HttpSessionContextIntegrati
4、onFilter,位于过滤器顶端,第一个起作用的过滤器。用途一,在执行其他过滤器之前,率先判断用户的session中是否已经存在一个SecurityContext了。如果存在,就把SecurityContext拿出来,放到SecurityContextHolder中,供Spring Security的其他部分使用。如果不存在,就创建一个SecurityContext出来,还是放到SecurityContextHolder中,供Spring Security的其他部分使用。用途二,在所有过滤器执行完毕后,清空SecurityContextHolder,因为SecurityContextHolde
5、r是基于ThreadLocal的,如果在操作完成后清空ThreadLocal,会受到服务器的线程池机制的影响。,LogoutFilter,只处理注销请求,默认为/j_spring_security_logout。用途是在用户发送注销请求时,销毁用户session,清空SecurityContextHolder,然后重定向到注销成功页面。可以与rememberMe之类的机制结合,在注销的同时清空用户cookie。,AuthenticationProcessingFilter,处理form登陆的过滤器,与form登陆有关的所有操作都是在此进行的。默认情况下只处理/j_spring_security
6、_check请求,这个请求应该是用户使用form登陆后的提交地址。此过滤器执行的基本操作时,通过用户名和密码判断用户是否有效,如果登录成功就跳转到成功页面(可能是登陆之前访问的受保护页面,也可能是默认的成功页面),如果登录失败,就跳转到失败页面。,登陆 用户:密码:两周之内不必登陆,/j_spring_security_check,提交登陆信息的URL地址。自定义form时,要把form的action设置为/j_spring_security_check。注意这里要使用绝对路径,避免登陆页面存放的页面可能带来的问题。j_username,输入登陆名的参数名称。j_password,输入密码的参
7、数名称_spring_security_remember_me,选择是否允许自动登录的参数名称。可以直接把这个参数设置为一个checkbox,无需设置value,Spring Security会自行判断它是否被选中。,DefaultLoginPageGeneratingFilter,此过滤器用来生成一个默认的登录页面,默认的访问地址为/spring_security_login,这个默认的登录页面虽然支持用户输入用户名,密码,也支持rememberMe功能,但是因为太难看了,只能是在演示时做个样子,不可能直接用在实际项目中。自定义登陆页面,BasicProcessingFilter,此过滤器用
8、于进行basic验证,功能与AuthenticationProcessingFilter类似,只是验证的方式不同。添加basic认证,去掉auto-config=true,并加上,SecurityContextHolderAwareRequestFilter,此过滤器用来包装客户的请求。目的是在原始请求的基础上,为后续程序提供一些额外的数据。比如getRemoteUser()时直接返回当前登陆的用户名之类的。,ExceptionTranslationFilter,此过滤器的作用是处理中FilterSecurityInterceptor抛出的异常,然后将请求重定向到对应页面,或返回对应的响应错误
9、代码。,RememberMeProcessingFilter,此过滤器实现RememberMe功能,当用户cookie中存在rememberMe的标记,此过滤器会根据标记自动实现用户登陆,并创建SecurityContext,授予对应的权限。在配置文件中使用auto-config=true就会自动启用rememberMe实际上,Spring Security中的rememberMe是依赖cookie实现的,当用户在登录时选择使用rememberMe,系统就会在登录成功后将为用户生成一个唯一标识,并将这个标识保存进cookie中,我们可以通过浏览器查看用户电脑中的cookie。,Anonymou
10、sProcessingFilter,为了保证操作统一性,当用户没有登陆时,默认为用户分配匿名用户的权限。在配置文件中使用auto-config=true就会启用匿名登录功能。在启用匿名登录之后,如果我们希望允许未登录就可以访问一些资源,可以在进行如下配置。设置成 ROLE_ANONYMOUS 也可以。,filters=none表示当我们访问“/”时,是不会使用任何一个过滤器去处理这个请求的,它可以实现无需登录即可访问资源的效果,但是因为没有使用过滤器对请求进行处理,所以也无法利用安全过滤器为我们带来的好处,最简单的,这时SecurityContext内再没有保存任何一个权限主体了,我们也无法从
11、中取得主体名称以及对应的权限信息。,ExceptionTranslationFilter,此过滤器的作用是处理中FilterSecurityInterceptor抛出的异常,然后将请求重定向到对应页面,或返回对应的响应错误代码。,SessionFixationProtectionFilter,防御会话伪造攻击。解决session fix的问题其实很简单,只要在用户登录成功之后,销毁用户的当前session,并重新生成一个session就可以了。session-fixation-protection的值共有三个可供选择,none,migrateSession和newSession。默认使用的是m
12、igrationSession,FilterSecurityInterceptor,用户的权限控制都包含在这个过滤器中。功能一:如果用户尚未登陆,则抛出AuthenticationCredentialsNotFoundException“尚未认证异常”。功能二:如果用户已登录,但是没有访问当前资源的权限,则抛出AccessDeniedException“拒绝访问异常”。功能三:如果用户已登录,也具有访问当前资源的权限,则放行。至此,我们完全展示了默认情况下Spring Security中使用到的过滤器,以及每个过滤器的应用场景和显示功能,下面我们会对这些过滤器的配置和用法进行逐一介绍。,Spr
13、ing Security 基本配置,最小化配置 1.在web.xml文件中加入Filter声明 Xml代码 springSecurityFilterChain springSecurityFilterChain/*这个Filter会拦截所有的URL请求,并且对这些URL请求进行Spring Security的验证。注意,springSecurityFilterChain这个名称是由命名空间默认创建的用于处理web安全的一个内部的bean的id。所以你在你的Spring配置文件中,不应该再使用这个id作为你的bean。,2.使用最小的配置 Xml代码 这段配置表示:1:只有拥有ROLE_ADMI
14、N角色的用户才可以访问/admin.jsp。2:拥有ROLE_USER角色的用户,可以访问应用程序中的所有URL。你可以使用多个元素为不同URL的集合定义不同的访问需求,它们会被归入一个有序队列中,每次取出最先匹配的一个元素使用。所以你必须把期望使用的匹配条件放到最上边。,自定义登录页面,让没登陆的用户也可以访问login.jsp。这是因为配置文件中的“/*”配置,要求用户访问任意一个系统资源时,必须拥有ROLE_USER角色,/login.jsp也不例外,如果我们不为/login.jsp单独配置访问权限,会造成用户连登陆的权限都没有,这是不正确的。login-page表示用户登陆时显示我们自
15、定义的login.jsp。这时我们访问系统显示的登陆页面将是我们上面创建的login.jsp。authentication-failure-url表示用户登陆失败时,跳转到哪个页面。当用户输入的登录名和密码不正确时,系统将再次跳转到/login.jsp,并添加一个error=true参数作为登陆失败的标示。default-target-url表示登陆成功时,跳转到哪个页面,剖析基本配置元素 1.有关auto-config属性 在上面用到的auto-config属性,其实是下面这些配置的缩写:Xml代码 这些元素分别与登录认证,匿名认证,基本认证,注销处理和remember-me对应。他们拥有各
16、自的属性,可以改变他们的具体行为。这样,我们在Acegi中所熟悉的元素又浮现在我们的面前(备注)。只是在这里,我们使用的是命名空间而已。,这些过滤器已经被Spring容器默认内置注册,这也就是我们不再需要在配置文件中定义那么多bean的原因。同时,过滤器顺序在使用命名空间的时候是被严格执行的。它们在初始化的时候就预先被排好序。不仅如此,Spring Security规定,你不能替换那些元素自己使用而创建出的过滤器,比如HttpSessionContextIntegrationFilter,ExceptionTranslationFilter 或 FilterSecurityIntercepto
17、r。当然,这样的规定是否合理,有待进一步讨论。因为实际上在很多时候,我们希望覆盖过滤器链中的某个过滤器的默认行为。而Spring Security的这种规定在一定程度上限制了我们的行为。不过Spring Security允许你把你自己的过滤器添加到队列中,使用custom-filter元素,并且指定你的过滤器应该出现的位置:Xml代码,不仅如此,你还可以使用after或before属性,如果你想把你的过滤器添加到队列中另一个过滤器的前面或后面。再者你还可以分别在position属性使用FIRST或LAST来指定你的过滤器出现在队列元素的前面或后面。这个特性或许能够在一定程度上弥补Spring
18、Security的死板规定,而在之后的应用中,我也会把它作为切入点,对资源进行管理。另外,我需要补充一点的是,对于在http/intercept-url中没有进行定义的URL,将会默认使用系统内置的过滤器链进行权限认证。所以,你并不需要在http/intercept-url中额外定义一个类似/*的匹配规则。,采用数据库进行身份验证以及资源认证,把用户信息和权限信息放到了xml文件中,这是为了演示如何使用最小的配置就可以使用Spring Security,而实际开发中,用户信息和权限信息通常是被保存在数据库中的,为此Spring Security提供了通过数据库获得用户权限信息的方式。,通过扩展
19、Spring Security的默认实现来进行用户和权限的管理 事实上,Spring Security提供了2个认证的接口,分别用于模拟用户和权限,以及读取用户和权限的操作方法。这两个接口分别是:UserDetails和UserDetailsService。Java代码 publicinterfaceUserDetailsextendsSerializable GrantedAuthoritygetAuthorities();StringgetPassword();StringgetUsername();booleanisAccountNonExpired();booleanisAccount
20、NonLocked();booleanisCredentialsNonExpired();booleanisEnabled();,Java代码 publicinterfaceUserDetailsService UserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException,DataAccessException;非常清楚,一个接口用于模拟用户,另外一个用于模拟读取用户的过程。所以我们可以通过实现这两个接口,来完成使用数据库对用户和权限进行管理的需求。,public class UserDetailsSe
21、rivceImpl implements UserDetailsService UserDetails details=null;public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException,DataAccessException if(username.equals(admin)details=new User(admin,111,true,new GrantedAuthority new GrantedAuthorityImpl(ROLE_ADMIN);else if(usern
22、ame.equals(user)details=new User(user,222,true,new GrantedAuthority new GrantedAuthorityImpl(ROLE_USER);return details;,使用数据库对资源进行管理,import;import;import;import;import;import;import;import;public class RequestMapFactoryBean implements FactoryBean private LinkedHashMap requestMap;public void init()re
23、questMap=new LinkedHashMap();ConfigAttribute attribute=null;List roleList=null;RequestKey key=null;ConfigAttributeDefinition definition=null;,key=new RequestKey(/page/welcome.jsp);roleList=new ArrayList();roleList.add(new SecurityConfig(ROLE_USER);roleList.add(new SecurityConfig(ROLE_ADMIN);definiti
24、on=new ConfigAttributeDefinition(roleList);requestMap.put(key,definition);key=new RequestKey(/page/manage_1.jsp);attribute=new SecurityConfig(ROLE_ADMIN);definition=new ConfigAttributeDefinition(attribute);requestMap.put(key,definition);key=new RequestKey(/page/common_1.jsp);attribute=new SecurityCo
25、nfig(ROLE_USER);definition=new ConfigAttributeDefinition(attribute);requestMap.put(key,definition);,key=new RequestKey(/page/*);roleList=new ArrayList();roleList.add(new SecurityConfig(ROLE_ADMIN);roleList.add(new SecurityConfig(ROLE_USER);definition=new ConfigAttributeDefinition(roleList);requestMap.put(key,definition);public Object getObject()throws Exception if(requestMap=null)init();return requestMap;public Class getObjectType()return LinkedHashMap.class;public boolean isSingleton()return true;,谢谢!,