- 浏览: 292858 次
- 性别:
- 来自: 唐山
最新评论
-
小灯笼:
JBPM5.4实战流程引擎开发网盘地址:https://pan ...
跟我学工作流——jBPM4视频教程(免费) -
Kai_Ge:
学会做人 写道临远大哥,谢谢你的贡献大名鼎鼎的临远!!膜拜中。 ...
Spring Security-3.0.1中文官方文档(翻译版) -
漂泊一剑客:
博主,你自己电脑上有下载,这些信息吗,能否分享一下给我
跟我学工作流——jBPM4视频教程(免费) -
Rookie_Li:
您好,您的教程很有用,请问例子的源码在哪下载?
spring security权限管理手册升级至spring security-3.1.3 -
nullFFF:
马教授 写道现在还用4有点过时了,最新的都已经是5.4了,目前 ...
跟我学工作流——jBPM4视频教程(免费)
8.1. 机制,供应者和入口
如果你使用Spring Security提供的认证方式,你通常需要配置一个web过滤器,AuthenticationProvider 和 AuthenticationEntryPoint。 在这章里,我们将要研究一个应用例子,它要支持基于表单的认证(比如,把一个非常好的HTML页面展现给用户,让他们进行登录)和基本认证(比如一个web服务或类似可访问的被保护资源)。
在web.xml里,这个程序需要单独的Spring Security过滤器来使用FilterChainProxy。 几乎所有Spring Security程序都有这样一个入口,看起来像这样:
<filter>
<filter-name>filterChainProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>filterChainProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上面的声明会让所有web请求,都通过叫做filterChainProxy的bean,通常它是Spring Security的FilterChainProxy的一个实例。 就像在这个参考指南的过滤器章节解释的那样,FilterChainProxy是一个通用类,让web请求可以基于URL模式通过不同的过滤器。 那些被委派的过滤器都管理在application context中,这样它们可以从依赖注入获得更大的益处。 让我们看一下FilterChainProxy bean定义,在application context的形式就像这样:
<bean id="filterChainProxy"
class="org.springframework.security.util.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/**" filters="httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,switchUserProcessingFilter"/>
</security:filter-chain-map>
</bean>
安全命名空间里的filter-chain-map的语法,让你可以使用filter-chain子元素序列,为过滤器链定义一个URL映射。 它们使用pattern属性定义了一系列 URL,使用filters属性定义了过滤器链。 这里需要重点注意的是,过滤器系列会按照定义的顺序执行 - 而且每个过滤器,都与在application context中定义的其他bean的id相对应。 所以,我们看到一些特定的bean出现在application context里,他们可能叫作httpSessionContextIntegrationFilter,logoutFilter等等。 过滤器的顺序,在参考文档的过滤器章节讨论 - 不过上面的例子没有问题。
在我们的例子中,我们使用了AuthenticationProcessingFilter,BasicProcessingFilter。 他们是,响应基于表单认证和基本HTTP header认证的“认证机制”(我们在参考文档的前面部分讨论过认证机制的角色)。 如果你没有使用表单或基本认证,就不需要定义这几个bean。 你应该使用,你想要的认证环境需要的过滤器,比如DigestProcessingFilter或CasProcessingFilter。 参考有关这部分参考文档的单独章节,学习如何配置每个认证机制。
让我们回忆一下,HttpSessionContextIntegrationFilter保存了在HTTP session调用中的SecurityContext内容。 这意味着认证机制只在主体初始化尝试认证的时候使用一次。 剩下的时间里,认证机制就待在那里,静静的让请求通过,进入过滤器链的下一个过滤器里。 这是一个很现实的需求,认证过程很少需要在每个调用的时候起作用(BASIC认证是一个例外),但是,在初始化认证完成之后,如果主体帐号发生了取消或禁用或其他改变(比如,增加或减少授权GrantedAuthority[]),怎么办? 让我们看看现在是如何处理的。
安全对象的主要认证提供器在前面介绍过,是AbstractSecurityInterceptor。 这个类需要访问AuthenticationManager。 它也可以配置成,一个Authentication对象在每次安全对象调用的时候,是否需要重新认证。 默认情况下,如果Authentication.isAuthenticated()返回true,它就只从SecurityContextHolder中取得已经认证的Authentication。 这样执行很有效率,但是没办法处理即时认证的有效。 对这种情况,你就要把AbstractSecurityInterceptor.alwaysReauthenticate属性设置成true。
你可能会问自己,“AuthenticationManager是什么?”。 我们之前还没有讲过它,但是我们讨论过AuthenticationProvider的概念。 非常简单,一个AuthenticationManager用来从一个AuthenticationProvider链传递请求,获得响应。 这跟我们以前讨论到的过滤器链有点儿相似,虽然这里有很多区别。 在Spring Security里,这里只有一个AuthenticationManager实现,所以让我们看看,对于这章中的例子,它是如何配置的:
<bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>
还要提到一点,你的认证机制(通常是过滤器)也要注入AuthenticationManager的引用。 所以AbstractSecurityInterceptor作为一个认证机制,也要使用上面的ProviderManager轮询一系列的AuthenticationProvider。
在我们例子里有三个提供器。 他们按照顺序进行排列(这里使用的是List而不是Set),每个提供器都尝试进行认证,或跳过验证简单返回null。 如果所有实现都返回null,ProviderManager就会抛出一个对应的异常。 如果你对链装提供器感兴趣,请参考ProviderManager的JavaDocs。
这些提供器有时在不同认证机制之间是可互换的,其他时候,它们依赖于特定的认证机制。 比如DaoAuthenticationProvider只需要基于字符串的用户名和密码。 好多认证机制会产生基于字符串的用户名和密码的集合,包括(但不限于)表单和基本验证。 同样的,一些认证机制创建只能被对应AuthenticationProvider使用的认证请求对象。 比如,一一对应的JA-SIG CAS,他使用服务票据体型,只能被CasAuthenticationProvider认证。 另一个一一对应的例子是LDAP认证机制,它只会被LdapAuthenticationProvider处理。 每个类特定关系的细节在JavaDocs里,这个参考指南的认证特定方式的章节里都有详细说明。 你不需要特别注意这些实现细节,因为如果你忘记注册对应的提供器,你就会在尝试认证的时候收到一个ProviderNotFoundException。
在正确配置完FilterChainProxy里的认证机制后,也确定对应的AuthenticationProvider注册到了ProviderManager中,你最后一步是配置一个AuthenticationEntryPoint。 回忆一下我们以前讨论过的ExceptionTranslationFilter的角色,它是在认证开始的使用,用来在基于HTTP请求,返回一个HTTP头或HTTP重定向。 继续我们以前的例子:
<bean id="exceptionTranslationFilter"
class="org.springframework.security.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint"/>
<property name="accessDeniedHandler">
<bean class="org.springframework.security.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp"/>
</bean>
</property>
</bean>
<bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
<property name="forceHttps">< value="false"/>
</bean>
注意ExceptionTranslationFilter需要两个协作者。 第一个是AccessDeniedHandlerImpl,使用RequestDispatcher转向到显示特定访问拒绝错误页面。 我们使用请求转向,这样SecurityContextHolder还能包含着主体的信息,这对呈现给用户是很有用的(老版本中,我们让servlet容器处理403错误信息,这会丢失很多有用的内容信息)。 AccessDeniedHandlerImpl也会把HTTP header设置成403,这是一个正规的错误代码,描述拒绝访问。 至于AuthentionEntryPoint,这里我们设置当一个未认证的主体尝试执行一个安全操作时,会执行什么动作。 因为在我们的例子里,我们将使用基于表单的认证,我们指定AuthenticationProcessinFilterEntryPoint和登录用页面的URL。 你的程序通常只会有一个入口点,大多数的认证方法定义它们自己的AuthenticationEntryPoint。 每个认证方式对应哪个入口点,在参考指南的认证特定方式章节里讨论。
8.2. UserDetails 和相关类型
就像参考指南第一部分提到的,大多数认证提供器使用UserDetails 和 UserDetailsService 接口。 后一个接口只有一个单独的方法:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
返回的UserDetails是一个接口,提供了getter方法,保障非空的基本认证信息,比如用户名,密码,授予的权限,和这个用户是否被禁用了。 大多数认证提供器会使用UserDetailsService,即使用户名和密码其实没有在认证过程中用到。 通常,这种供应器会使用返回的UserDetails对象,只是使用其中的GrantedAuthority[]信息,因为一些系统(像LDAP或X509或CAS等等)已经对整数的有效性进行过验证。
一个由Spring Security提供的UserDetails单独的具体实现,是User类。 Spring Security用户将需要决定什么时候编写他们的UserDetailsService,返回具体的UserDetails类。 大多数情况下User会直接使用,或被继承,虽然特定的环境(比如ORM)可能需要用户根据脚手架编写他们自己的UserDetails。 这并不是不常见的情况,用户应该毫不犹豫的返回他们正常的领域对象,展示系统的一个用户。 尤其是通常给UserDetails提供附加的主体相关的属性(比如他们的电话号码和邮件地址),这样他们可以很容易在web视图里使用。
UserDetailsService是非常容易实现的,用户应该很容易使用他们自己选择持久化策略,获得认证信息。 这里,Spring Security确实包含了很多有用的实现,我们会在下面看到。
8.2.1. 内存里认证
虽然很容易创建一个自定义的UserDetailsService实现,从选择的持久化引擎里获得确切信息,不过很多应用不需要搞得这么复杂。 特别是在你进行一个快速原型或者仅仅开始集成Spring Security的时候,当你不是真的需要在配置数据库或写UserDetailsService实现上面花费时间的时候。 为了这种情况,一个简单的选择是使用安全命名空间里的user-service元素,:
<user-service id="userDetailsService">
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
它也支持外部属性文件:
<user-service id="userDetailsService" properties="users.properties"/>
属性文件,应该包含下面格式的内容
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
比如
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
bob=bobspassword,ROLE_USER,enabled
8.2.2. JDBC认证
Spring Security也包含一个UserDetailsService可以从JDBC数据源里获得认证信息。 内部使用了Spring JDBC,避免了仅仅为了保存用户信息而实现ORM完全功能的复杂性。 如果你的程序使用了ORM工具,你估计会喜欢自己写一个UserDetailsService来重用你已经写好的映射文件。 回到JdbcDaoImpl,一个配置的例子如下所示:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="jdbcDaoImpl" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
通过修改上面的DriverManagerDataSource,你可使用不同的关系型数据库管理系统。 你也可以使用通常的Spring选项,从JNDI获得的公共数据源。 不论什么什么数据库,或者,不管DataSource是如何获得的,必须用到一个标准的表结构,表结构定义的内容在dbinit.txt。 你可以从Spring Security网站上下载这个文件。
如果默认的表结构不满足你的需要,JdbcDaoImpl提供了两个属性,可以自定义SQL语句。 如果需要进行更多自定义,你可以继承JdbcDaoImpl。 请通过JavaDocs查找详细信息,不过请注意,这个类不是为复杂的自定义子类设计的。 如果你有非常复杂的需求(比如一个特定的表结构,或需要返回特定的实现UserDetails),你最好重写你自己的UserDetailsService。 这个Spring Security提供的基本实现,是为了典型情况,它并没有提供无限的配置灵活性。
8.3. 并行会话处理
Spring Security可以限制一个主体并行认证到同一系统的次数。 很多ISV利用这点来加强授权公里,网管也喜欢这个功能,因为它可以防止人们共享登录名。 你可以,比如,禁止用户"Batman"从两个不同的会话登录到web应用里。
要使用并行会话支持,你需要把下面内容添加到web.xml里:
<listener>
<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
另外,你需要把org.springframework.security.concurrent.ConcurrentSessionFilter添加到你的FilterChainProxy里。 ConcurrentSessionFilter需要两个属性,sessionRegistry,这个通常指向一个SessionRegistryImpl实例,和expiredUrl,在session过期的时候就指向这个页面。
web.xml里的HttpSessionEventPublisher会在 HttpSession 创建或销毁的时候,发送一个ApplicationEvent给 Spring的 ApplicationContext。 这是关键,它让SessionRegistryImpl 知道什么时候session结束了。
你还需要装配 ConcurrentSessionControllerImpl ,然后从你的 ProviderManager bean里引用它:
<bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<!-- your providers go here -->
</property>
<property name="sessionController" ref="concurrentSessionController"/>
</bean>
<bean id="concurrentSessionController"
class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl">
<property name="maximumSessions" value="1"/>
<property name="sessionRegistry">
<bean class="org.springframework.security.concurrent.SessionRegistryImpl"/>
<property>
</bean>
8.4. 认证标签库
AuthenticationTag只是用来把当前的Authentication对象的一个属性,输出到网页上。
下面的JSP片段,展示了如何使用 AuthenticationTag:
<security:authentication property="principal.username"/>
这个标签会把主体的名称显示出来。 这里我们假设Authentication.getPrincipal()是一个UserDetails对象,通常是由Spring Security的标准AuthenticationProvider实现的。
如果你使用Spring Security提供的认证方式,你通常需要配置一个web过滤器,AuthenticationProvider 和 AuthenticationEntryPoint。 在这章里,我们将要研究一个应用例子,它要支持基于表单的认证(比如,把一个非常好的HTML页面展现给用户,让他们进行登录)和基本认证(比如一个web服务或类似可访问的被保护资源)。
在web.xml里,这个程序需要单独的Spring Security过滤器来使用FilterChainProxy。 几乎所有Spring Security程序都有这样一个入口,看起来像这样:
<filter>
<filter-name>filterChainProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>filterChainProxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上面的声明会让所有web请求,都通过叫做filterChainProxy的bean,通常它是Spring Security的FilterChainProxy的一个实例。 就像在这个参考指南的过滤器章节解释的那样,FilterChainProxy是一个通用类,让web请求可以基于URL模式通过不同的过滤器。 那些被委派的过滤器都管理在application context中,这样它们可以从依赖注入获得更大的益处。 让我们看一下FilterChainProxy bean定义,在application context的形式就像这样:
<bean id="filterChainProxy"
class="org.springframework.security.util.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/**" filters="httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,switchUserProcessingFilter"/>
</security:filter-chain-map>
</bean>
安全命名空间里的filter-chain-map的语法,让你可以使用filter-chain子元素序列,为过滤器链定义一个URL映射。 它们使用pattern属性定义了一系列 URL,使用filters属性定义了过滤器链。 这里需要重点注意的是,过滤器系列会按照定义的顺序执行 - 而且每个过滤器,都与在application context中定义的其他bean的id相对应。 所以,我们看到一些特定的bean出现在application context里,他们可能叫作httpSessionContextIntegrationFilter,logoutFilter等等。 过滤器的顺序,在参考文档的过滤器章节讨论 - 不过上面的例子没有问题。
在我们的例子中,我们使用了AuthenticationProcessingFilter,BasicProcessingFilter。 他们是,响应基于表单认证和基本HTTP header认证的“认证机制”(我们在参考文档的前面部分讨论过认证机制的角色)。 如果你没有使用表单或基本认证,就不需要定义这几个bean。 你应该使用,你想要的认证环境需要的过滤器,比如DigestProcessingFilter或CasProcessingFilter。 参考有关这部分参考文档的单独章节,学习如何配置每个认证机制。
让我们回忆一下,HttpSessionContextIntegrationFilter保存了在HTTP session调用中的SecurityContext内容。 这意味着认证机制只在主体初始化尝试认证的时候使用一次。 剩下的时间里,认证机制就待在那里,静静的让请求通过,进入过滤器链的下一个过滤器里。 这是一个很现实的需求,认证过程很少需要在每个调用的时候起作用(BASIC认证是一个例外),但是,在初始化认证完成之后,如果主体帐号发生了取消或禁用或其他改变(比如,增加或减少授权GrantedAuthority[]),怎么办? 让我们看看现在是如何处理的。
安全对象的主要认证提供器在前面介绍过,是AbstractSecurityInterceptor。 这个类需要访问AuthenticationManager。 它也可以配置成,一个Authentication对象在每次安全对象调用的时候,是否需要重新认证。 默认情况下,如果Authentication.isAuthenticated()返回true,它就只从SecurityContextHolder中取得已经认证的Authentication。 这样执行很有效率,但是没办法处理即时认证的有效。 对这种情况,你就要把AbstractSecurityInterceptor.alwaysReauthenticate属性设置成true。
你可能会问自己,“AuthenticationManager是什么?”。 我们之前还没有讲过它,但是我们讨论过AuthenticationProvider的概念。 非常简单,一个AuthenticationManager用来从一个AuthenticationProvider链传递请求,获得响应。 这跟我们以前讨论到的过滤器链有点儿相似,虽然这里有很多区别。 在Spring Security里,这里只有一个AuthenticationManager实现,所以让我们看看,对于这章中的例子,它是如何配置的:
<bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>
还要提到一点,你的认证机制(通常是过滤器)也要注入AuthenticationManager的引用。 所以AbstractSecurityInterceptor作为一个认证机制,也要使用上面的ProviderManager轮询一系列的AuthenticationProvider。
在我们例子里有三个提供器。 他们按照顺序进行排列(这里使用的是List而不是Set),每个提供器都尝试进行认证,或跳过验证简单返回null。 如果所有实现都返回null,ProviderManager就会抛出一个对应的异常。 如果你对链装提供器感兴趣,请参考ProviderManager的JavaDocs。
这些提供器有时在不同认证机制之间是可互换的,其他时候,它们依赖于特定的认证机制。 比如DaoAuthenticationProvider只需要基于字符串的用户名和密码。 好多认证机制会产生基于字符串的用户名和密码的集合,包括(但不限于)表单和基本验证。 同样的,一些认证机制创建只能被对应AuthenticationProvider使用的认证请求对象。 比如,一一对应的JA-SIG CAS,他使用服务票据体型,只能被CasAuthenticationProvider认证。 另一个一一对应的例子是LDAP认证机制,它只会被LdapAuthenticationProvider处理。 每个类特定关系的细节在JavaDocs里,这个参考指南的认证特定方式的章节里都有详细说明。 你不需要特别注意这些实现细节,因为如果你忘记注册对应的提供器,你就会在尝试认证的时候收到一个ProviderNotFoundException。
在正确配置完FilterChainProxy里的认证机制后,也确定对应的AuthenticationProvider注册到了ProviderManager中,你最后一步是配置一个AuthenticationEntryPoint。 回忆一下我们以前讨论过的ExceptionTranslationFilter的角色,它是在认证开始的使用,用来在基于HTTP请求,返回一个HTTP头或HTTP重定向。 继续我们以前的例子:
<bean id="exceptionTranslationFilter"
class="org.springframework.security.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint"/>
<property name="accessDeniedHandler">
<bean class="org.springframework.security.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp"/>
</bean>
</property>
</bean>
<bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
<property name="forceHttps">< value="false"/>
</bean>
注意ExceptionTranslationFilter需要两个协作者。 第一个是AccessDeniedHandlerImpl,使用RequestDispatcher转向到显示特定访问拒绝错误页面。 我们使用请求转向,这样SecurityContextHolder还能包含着主体的信息,这对呈现给用户是很有用的(老版本中,我们让servlet容器处理403错误信息,这会丢失很多有用的内容信息)。 AccessDeniedHandlerImpl也会把HTTP header设置成403,这是一个正规的错误代码,描述拒绝访问。 至于AuthentionEntryPoint,这里我们设置当一个未认证的主体尝试执行一个安全操作时,会执行什么动作。 因为在我们的例子里,我们将使用基于表单的认证,我们指定AuthenticationProcessinFilterEntryPoint和登录用页面的URL。 你的程序通常只会有一个入口点,大多数的认证方法定义它们自己的AuthenticationEntryPoint。 每个认证方式对应哪个入口点,在参考指南的认证特定方式章节里讨论。
8.2. UserDetails 和相关类型
就像参考指南第一部分提到的,大多数认证提供器使用UserDetails 和 UserDetailsService 接口。 后一个接口只有一个单独的方法:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
返回的UserDetails是一个接口,提供了getter方法,保障非空的基本认证信息,比如用户名,密码,授予的权限,和这个用户是否被禁用了。 大多数认证提供器会使用UserDetailsService,即使用户名和密码其实没有在认证过程中用到。 通常,这种供应器会使用返回的UserDetails对象,只是使用其中的GrantedAuthority[]信息,因为一些系统(像LDAP或X509或CAS等等)已经对整数的有效性进行过验证。
一个由Spring Security提供的UserDetails单独的具体实现,是User类。 Spring Security用户将需要决定什么时候编写他们的UserDetailsService,返回具体的UserDetails类。 大多数情况下User会直接使用,或被继承,虽然特定的环境(比如ORM)可能需要用户根据脚手架编写他们自己的UserDetails。 这并不是不常见的情况,用户应该毫不犹豫的返回他们正常的领域对象,展示系统的一个用户。 尤其是通常给UserDetails提供附加的主体相关的属性(比如他们的电话号码和邮件地址),这样他们可以很容易在web视图里使用。
UserDetailsService是非常容易实现的,用户应该很容易使用他们自己选择持久化策略,获得认证信息。 这里,Spring Security确实包含了很多有用的实现,我们会在下面看到。
8.2.1. 内存里认证
虽然很容易创建一个自定义的UserDetailsService实现,从选择的持久化引擎里获得确切信息,不过很多应用不需要搞得这么复杂。 特别是在你进行一个快速原型或者仅仅开始集成Spring Security的时候,当你不是真的需要在配置数据库或写UserDetailsService实现上面花费时间的时候。 为了这种情况,一个简单的选择是使用安全命名空间里的user-service元素,:
<user-service id="userDetailsService">
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
它也支持外部属性文件:
<user-service id="userDetailsService" properties="users.properties"/>
属性文件,应该包含下面格式的内容
username=password,grantedAuthority[,grantedAuthority][,enabled|disabled]
比如
jimi=jimispassword,ROLE_USER,ROLE_ADMIN,enabled
bob=bobspassword,ROLE_USER,enabled
8.2.2. JDBC认证
Spring Security也包含一个UserDetailsService可以从JDBC数据源里获得认证信息。 内部使用了Spring JDBC,避免了仅仅为了保存用户信息而实现ORM完全功能的复杂性。 如果你的程序使用了ORM工具,你估计会喜欢自己写一个UserDetailsService来重用你已经写好的映射文件。 回到JdbcDaoImpl,一个配置的例子如下所示:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="jdbcDaoImpl" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource" ref="dataSource"/>
</bean>
通过修改上面的DriverManagerDataSource,你可使用不同的关系型数据库管理系统。 你也可以使用通常的Spring选项,从JNDI获得的公共数据源。 不论什么什么数据库,或者,不管DataSource是如何获得的,必须用到一个标准的表结构,表结构定义的内容在dbinit.txt。 你可以从Spring Security网站上下载这个文件。
如果默认的表结构不满足你的需要,JdbcDaoImpl提供了两个属性,可以自定义SQL语句。 如果需要进行更多自定义,你可以继承JdbcDaoImpl。 请通过JavaDocs查找详细信息,不过请注意,这个类不是为复杂的自定义子类设计的。 如果你有非常复杂的需求(比如一个特定的表结构,或需要返回特定的实现UserDetails),你最好重写你自己的UserDetailsService。 这个Spring Security提供的基本实现,是为了典型情况,它并没有提供无限的配置灵活性。
8.3. 并行会话处理
Spring Security可以限制一个主体并行认证到同一系统的次数。 很多ISV利用这点来加强授权公里,网管也喜欢这个功能,因为它可以防止人们共享登录名。 你可以,比如,禁止用户"Batman"从两个不同的会话登录到web应用里。
要使用并行会话支持,你需要把下面内容添加到web.xml里:
<listener>
<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
另外,你需要把org.springframework.security.concurrent.ConcurrentSessionFilter添加到你的FilterChainProxy里。 ConcurrentSessionFilter需要两个属性,sessionRegistry,这个通常指向一个SessionRegistryImpl实例,和expiredUrl,在session过期的时候就指向这个页面。
web.xml里的HttpSessionEventPublisher会在 HttpSession 创建或销毁的时候,发送一个ApplicationEvent给 Spring的 ApplicationContext。 这是关键,它让SessionRegistryImpl 知道什么时候session结束了。
你还需要装配 ConcurrentSessionControllerImpl ,然后从你的 ProviderManager bean里引用它:
<bean id="authenticationManager"
class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<!-- your providers go here -->
</property>
<property name="sessionController" ref="concurrentSessionController"/>
</bean>
<bean id="concurrentSessionController"
class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl">
<property name="maximumSessions" value="1"/>
<property name="sessionRegistry">
<bean class="org.springframework.security.concurrent.SessionRegistryImpl"/>
<property>
</bean>
8.4. 认证标签库
AuthenticationTag只是用来把当前的Authentication对象的一个属性,输出到网页上。
下面的JSP片段,展示了如何使用 AuthenticationTag:
<security:authentication property="principal.username"/>
这个标签会把主体的名称显示出来。 这里我们假设Authentication.getPrincipal()是一个UserDetails对象,通常是由Spring Security的标准AuthenticationProvider实现的。
发表评论
-
spring security权限管理手册升级至spring security-3.1.3
2012-12-08 01:01 12296费了半天劲,终于把原来基于spring security 2. ... -
请把acegi替换成Spring Security(内附视频)
2010-03-22 09:54 6562在对web项目进行权限管理时,采用的方法无非是写一大堆JSP或 ... -
Spring Security-3.0.1中文官方文档(翻译版)
2010-01-19 09:36 10644这次发布的Spring Security-3.0.1是一个bu ... -
敬献Spring Security-3.x官方文档中文版
2009-12-29 11:43 10879Spring Security-3.x新近发布,整体的项 ... -
【分享】《基于Spring Security的ACL实现与扩展》内附ppt下载
2009-09-21 09:43 3451上次朋友间技术交流整理的ppt文档,因为之前一直在整理Spri ... -
Spring Security 安全权限管理手册(0.1.0更新)
2009-08-05 10:26 5034随着内容的堆叠,文档结构开始渐渐混乱了,到0.1.0为止关于认 ... -
Spring Security 安全权限管理手册(0.0.9更新)
2009-07-27 09:27 3278这次更新中包含了一个在用户输入密码错误三次后锁定账户的示 ... -
Spring Security 安全权限管理手册(0.0.8更新)
2009-07-20 09:58 1890Spring Security-2.0.5发布,这个bug ... -
Spring Security 安全权限管理手册(0.0.7更新)
2009-07-13 00:38 3196这一次迭代,对章节的命名进行了这里,目标是尽快覆盖Spring ... -
Spring Security 安全权限管理手册(0.0.6更新)
2009-07-10 01:54 1669这一次,我们添加了taglib标签库的时候,以及如何使用多种方 ... -
Spring Security手册更新cas, basic, acl
2009-06-29 18:13 2670这次更新的都是重头戏,CAS和ACL。其中ACL只是简述了Sp ... -
Spring Security手册更新——添加“管理会话”和对namespace,database
2009-06-22 10:04 1942新增的部分有,第八章“管理会话”,附录D,E分别整 ... -
图解Spring Security默认使用的过滤器
2009-06-15 10:38 3860第 9 章 图解过滤器 图 9.1. au ... -
Spring Security-2.0导航-基础篇,又添两章
2009-06-10 10:31 1916目前我们在基础篇中已经编写了六章,基本上可 ... -
Spring Security-2.0入门教程(基础篇)
2009-06-04 17:48 4775欢迎阅读咱们写的Spring Security教程,咱们既不想 ... -
springsecurity-2.x官方文档中文翻译初步整理完成,附上几个例子
2008-08-17 11:12 7891预览地址:http://family168.com/tutor ... -
(翻译)Spring Security-2.0.x参考文档“领域对象安全”
2008-08-13 00:18 2199领域对象安全 24.1. 概述 请注意:在2.0.0之前,S ... -
(翻译)Spring Security-2.0.x参考文档“安全对象实现”
2008-08-12 09:50 2027安全对象实现 23.1. AOP联盟 (MethodInvoc ... -
(翻译)Spring Security-2.0.x参考文档“通用授权概念”
2008-08-11 18:22 2820通用授权概念 22.1. 授权 在认证部分简略提过了,所有的 ... -
(翻译)Spring Security-2.0.x参考文档“安全数据库表结构”
2008-08-10 09:52 2035安全数据库表结构 可以为框架采用不同的数据库结构,这个附录为 ...
相关推荐
包含翻译后的API文档:spring-security-core-5.3.9.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-core:5.3.9.RELEASE; 标签:springframework、security...
spring-beans-2.0.xsd
包含翻译后的API文档:spring-security-core-5.2.0.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-core:5.2.0.RELEASE; 标签:springframework、security...
包含翻译后的API文档:spring-security-oauth2-2.3.5.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security.oauth:spring-security-oauth2:2.3.5.RELEASE; 标签:spring、security...
包含翻译后的API文档:spring-security-rsa-1.0.10.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-rsa:1.0.10.RELEASE; 标签:spring、rsa、security、...
包含翻译后的API文档:spring-security-jwt-1.0.10.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-jwt:1.0.10.RELEASE; 标签:spring、security、jwt、...
包含翻译后的API文档:spring-security-web-5.2.0.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-web:5.2.0.RELEASE; 标签:springframework、security、...
spring-boot-starter-web-2.0.7.0.jar
spring-dwr-2.0.xsd spring 与 DWR进行配置
包含翻译后的API文档:spring-boot-actuator-autoconfigure-2.3.12.RELEASE-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.springframework.boot:spring-boot-actuator-autoconfigure:2.3.12....
Struts2-Spring-Plugin-2.0.11.1版本是在2.0.11.1时期发布的,可能包含了一些特定的修复和优化,具体可以查阅该版本的发行说明或官方文档,以了解其特性、改进和已知问题。 在使用这个插件时,你需要在Struts2的...
包含翻译后的API文档:spring-security-oauth2-2.3.5.RELEASE-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.springframework.security.oauth:spring-security-oauth2:2.3.5.RELEASE; 标签:spring...
包含翻译后的API文档:spring-security-core-5.0.7.RELEASE-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-core:5.0.7.RELEASE; 标签:springframework、security...
spring-aop-2.0.jar spring-aop-2.5.1.jar spring-aop-2.5.2.jar spring-aop-2.5.4.jar spring-aop-2.5.5.jar spring-aop-2.5.6.jar spring-aop-3.0.0.RELEASE.jar spring-aop-3.0.2.RELEASE.jar spring-aop-sources...
包含翻译后的API文档:spring-security-crypto-5.6.1-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-crypto:5.6.1; 标签:spring、security、springframework、...
包含翻译后的API文档:spring-security-jwt-1.0.10.RELEASE-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.springframework.security:spring-security-jwt:1.0.10.RELEASE; 标签:spring、security...
包含翻译后的API文档:spring-security-crypto-5.5.2-javadoc-API文档-中文(简体)版.zip; Maven坐标:org.springframework.security:spring-security-crypto:5.5.2; 标签:springframework、security、spring、...
首先,`struts-2.0.dtd`是Struts 2.0的文档类型定义,它是XML文件的一种规范,用于验证`struts.xml`配置文件的语法是否正确。DTD中定义了配置元素和属性,如action、result、package等,确保开发者在编写配置文件时...
spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-dependencies.zip spring-framework-2.0-with-...