`
kingoal
  • 浏览: 156579 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring Security使用指南 -- 名词空间配置篇

    博客分类:
  • Java
阅读更多
安全名词空间配置
简介
名词空间配置是从Spring框架2.0才有的功能。它将取代过去的Spring bean的应用程序上下文语法和额外的XML schema的元素。了解更多详情请参考Spring参考手册。一个名词空间元素将简单地实现配置一个具体的bean,并且功能更加强大地实现问题域的要求,为使用者隐藏底层的复杂性。一个简单的元素可以隐藏加在应用程序上下文上的多个beans和处理步骤。如下面的一个安全名词空间元素为应用程序上下文为测试而已起来一个嵌入式LDAP服务器。
<security:ldap-server />
这样比使用一个相当的Apache Directory Server beans来说要简单多了。最常用的替代配置是使用ldap-server元素,这样就可以不用担心究竟使用那个beans,并且为那个beans设置什么属性之类的。使用XML编辑器编辑应用程序上下文的时候需要提供属性与元素等相关的信息。我们推荐你使用SpringSource Tool Suite工具,该工具能够很好地处理Spring品牌的名词空间。
在你的应用程序上下文中使用安全名词空间的时候,你将需要在该上下文文件中添加如下的schema的申明:
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:security="http://www.springframework.org/schema/security"
  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-2.0.xsd
              http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
    ...
</beans>
在很多的应用程序中(如在例子里)我们将使用security作为默认的名词空间,而不是beans,这样我们就可以忽略名词空间元素的前缀,使得上下文更加容易地阅读。如果你将应用程序上下文分成好几个单独的文件,并且将安全相关的配置放到其中的一个文件中,你也可以这么来作。在你的安全相关的应用程序上下文文件中你将这样开始的:
<beans:beans xmlns="http://www.springframework.org/schema/security"
   xmlns:beans="http://www.springframework.org/schema/beans">
    ...
</beans:beans>
从这章开始,我们就开始使用这个语法。
我从例子程序上看是这样来配置的:
<beans:beans xmlns="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-2.0.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
</beans:beans>
名词空间设计
安全名词空间是为框架中常用的操作提供简单并且具体的语法以便方便应用程序的使用。这些名词空间主要是分如下几个方面:
Web/HTTP Security - 最复杂的部分。设置filter以及与框架认证机制相关的服务beans,安全的URL以及Login/出错页面等等。
Business Object (Method) Security - 服务层安全选项
AuthenticationManager - 处理来自框架其他部分的认证请求
AccessDecisionManager – 为web安全和方法安全提供访问决策。默认的将被注册登记,但是你也可以使用一个自定义的,使用Spring bean的语法
AuthenticationProviders - 为认证管理器来管理已经认证的用户的机制。这个名词空间提供多个标准的选项,同样可以使用传统的语法来添加定制化的beans。
UserDetailsService - 跟认证提供者紧密关联,同时也是为其他的beans提供服务
在下面的章节中我们将介绍如何使得他们一起工作的。

开始安全名词空间配置
在这一节里面,我们将查看如何搭建一个名词空间配置来使用该框架提供的主要功能。我们现假设你首先想在一个现有的web应用程序里尽可能快地将它运行起来,添加认证支持以及访问控制,登录方面的测试。然后我们将更改数据库方面的认证以及其他的安全信息数据源。最最后我们将介绍其他的高级名词空间配置选项。
web.xml配置
第一件事情就是在web.xml文件里面添加下面filter的声明:
<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>
这样就添加了Spring Security的web基础设施。然后你可以开始编辑你的应用程序上下文文件了。web安全服务是使用<http>元素来进行配置的。
最小的<http>配置
你将使用下面的设置来开启安全名词空间设置之旅:
  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER" />
  </http>
这就是说你的应用程序里面所有的URLs都有有ROLE_USER的角色才能够访问的安全认证。
当然你可以使用多个<intercept-url>元素来设置不同URL集合的不同访问需求,但是在使用具体的设置的时候是按照顺序来进行的,最后使用的第一个相符的设置,因此,你将在最上面放置最特殊的设置(put the most specific matches at the top)。
为了便于测试,可以在名词空间中添加如下一些测试数据
  <authentication-provider>
    <user-service>
      <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
      <user name="bob" password="bobspassword" authorities="ROLE_USER" />
    </user-service>
  </authentication-provider>
上面的配置是定义了2个用户,他们的密码以及在应用程序中的角色(用来作访问控制的)。这也有可以从标准属性文件中读取user-service用户信息数据properties属性。查看in-memory认证一节了解更多详情。使用<authentication-provider>元素意味着这些用户信息将被authentication manager用来处理认证请求。
现在你可以启动你的应用程序,并且需要你登录之后才能够继续运行。为了便于实验,你可以运行框架自带的tutorial例子程序。上面的配置事实上只是为应用程序添加了一小部分的服务, 因为我们使用了auto-config属性。举个例子,窗口认证登录处理以及记住我服务将自动开启。
Auto-config包括那些东西?
上面例子中用到的auto-config属性实际上是如下的语法的速写:
  <http>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <form-login />
    <anonymous />
    <http-basic />
    <logout />
    <remember-me />
  </http>
其他的元素表示的是form-login,匿名认证,基本的认证,注销处理以及记住我服务。它们每个都有自己的属性来表示不同的行为。
auto-config需要UserDetailsService
在你的应用程序中如果你使用auto-config但是没有UserDetailsService的话,将会报错。这是因为在auto-config=”true”中包括有记住我这个功能是打开的,而记住我这个功能是需要UserDetailsService信息来进行认证的。如果你有因为缺少UserDetailsService而报错,那么将去掉auto-config(以及所有的remember-me设置)。
Form和Basic登录选项
我们没有提到任何的HTML文件或者JSP,你也许在奇怪我们怎么会到达登录页面。事实上,我们不需要特殊地指定一个URL作为登录页面,Spring Security自动生成了一个,那样在用户需要登录的时候自动转向登录也没。当然,名词空间中支持你自定义这些选项。举个例子,你可以提供你自己的登录页面,通过如下的设置来进行设置:
  <http auto-config='true'>
    <intercept-url pattern="/login.jsp*" filters="none"/>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <form-login login-page='/login.jsp'/>
  </http>
特意提出来的是你仍可以使用auto-config。form-login元素将覆盖默认的设置。同时也可以设置登录页面不需要经过安全filter处理的。否则,因为没有登录,就不可能访问到登录也没。如果你想使用basic认证,你将上面的设置改变为:
  <http auto-config='true'>
    <intercept-url pattern="/**" access="ROLE_USER" />
    <http-basic />
  </http>
当用户试着去访问一个受保护的资源时,Basic认证将提升用户登录。如果你想在使用Form登录,也可以在这个配置中使用,举例来说就是在另外一个web页面中嵌入登录窗口。
使用其他的认证者(Authentication Provider)
实际上你有可能需要在应用程序上下文文件中添加更加具有可扩展性的用户信息。举例来说就是你有可能将你的用户信息保存在数据库或者LDAP服务器上。在LDAP章中我们将介绍LDAP名词空间配置,在这儿我们不详细展开。如果你想自定义地实现Spring Security的UserDetailsServer,如在你的应用程序上下文中使用myUserDetailsService,我们就使用下面的方式进行认证:
  <authentication-provider user-service-ref='myUserDetailsService'/>
如果你使用数据库来进行认证,可以这样设置:
  <authentication-provider>
    <jdbc-user-service data-source-ref="securityDataSource"/>
  </authentication-provider>
SecurityDataSource是应用程序上下文中的一个DataSource bean名字,指向包括Spring Security用户数据表的数据库。替代的情况你也可以使用Spring Security的JdbcDaoImpl bean来作为user-service-ref属性的值。
添加一个密码编码器
通常你的密码数据需要使用hash算法来进行编码。这是通过<password-encoder>这个元素来支持的。使用SHA编码密码,那authentication provider配置如下:
<authentication-provider>
  <password-encoder hash="sha"/>
  <user-service>
    <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f" authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f" authorities="ROLE_USER" />
  </user-service>
</authentication-provider>
使用hashed的密码,最好的办法是使用salt值来保护密码免受字典攻击,Spring Security支持该功能。理想情况是最好使用一个为每个用户随机生成的salt值,当然你也可以使用由UserDetailsService加载的UserDetails对象中的任意属性。举例说明,如果使用username属性作为salt值,则设置如下:
<password-encoder hash="sha">
  <salt-source user-property="username"/>
</password-encoder>
你也可以使用一种自定义化的密码编码器bean,然后使用password-encoder的ref属性来进行设置。只需要实现Spring Security的PasswordEncoder接口就可以了。
高级的web特性
“记住我”认证
查看Remember-Me章节来访问remember-me的名词空间设置。
加上http/https信道安全(channel security)
如果你的应用程序同时支持http和https,并且在某些URL必须要使用HTTPS来访问,那在Spring Security中需要如下的方式进行设置:
  <http>
    <intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/>
    <intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>
    ...
  </http>
在上面的配置中,如果用户使用HTTP的方式来访问/secure/**,那么将被重定向到HTTPS URL上。Requires-channel的选项有http, https, any。Any意味就是可以使用HTTP或者HTTPS。
如果你的应用程序不是使用标准的HTTP和HTTPS端口,那么就可以设定如下的端口映射:
  <http>
    ...
    <port-mappings>
      <port-mapping http="9080" https="9443"/>
    </port-mappings>
  </http>
更多的有关信道安全方面的知识,请参考第7章,信道安全。
并发session控制
如果你想控制单个用户登录到你的应用程序的能力,Spring Security支持这个功能,只需要在你的应用程序里面添加少量的改动就可。首先你需要在你的web.xml文件中添加session生存周期事件的监听器:
<listener>
  <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
</listener>
然后你在应用程序上下文添加如下的配置:
  <http>
    ...
    <concurrent-session-control max-sessions="1" />
  </http>
这样当有第二个session登录的时候,前面的一个就失效了。当时我们常常是使用下面的配置:
  <http>
    ...
    <concurrent-session-control max-sessions="1" exception-if-maximum-exceeded="true"/>
  </http>
这样就阻止第二个登录了。
OpenID登录
**感觉是一个第三方的登录认证,不感兴趣**
添加自己定义的Filter
If you've used Spring Security before, you'll know that the framework maintains a chain of filters in order to apply its services. You may want to add your own filters to the stack at particular locations, or use a customized version of an existing filter. How can you do this with namespace configuration, since the filter chain is not directly exposed?
如果你过去使用过Spring Security的话,那你一定知道该框架维护了一连串的filters来实现安全方面的功能。你可以在filters堆栈中添加自己定义的filter或者个性化设置现存的filter。那我们怎么通过名词空间配置来更改filter链呢?
在使用名词空间的时候filters的顺序是非常重要的。每一个Spring Security的filter实现了Spring的有序的接口,并且按照已经排好序的进行初始化。标准的filters在名词空间中有如下的别名:
Alias
Filter Class
CHANNEL_FILTER
ChannelProcessingFilter
CONCURRENT_SESSION_FILTER
ConcurrentSessionFilter
SESSION_CONTEXT_INTEGRATION_FILTER
HttpSessionContextIntegrationFilter
LOGOUT_FILTER
LogoutFilter
X509_FILTER
X509PreAuthenticatedProcessigFilter
PRE_AUTH_FILTER
Subclass of AstractPreAuthenticatedProcessingFilter
CAS_PROCESSING_FILTER
CasProcessingFilter
AUTHENTICATION_PROCESSING_FILTER
AuthenticationProcessingFilter
BASIC_PROCESSING_FILTER
BasicProcessingFilter
SERVLET_API_SUPPORT_FILTER
Classname
REMEMBER_ME_FILTER
RememberMeProcessingFilter
ANONYMOUS_FILTER
AnonymousProcessingFilter
EXCEPTION_TRANSLATION_FILTER
ExceptionTranslationFilter
NTLM_FILTER
NtlmProcessingFilter
FILTER_SECURITY_INTERCEPTOR
FilterSecurityInterceptor
SWITCH_USER_FILTER
SwitchUserProcessingFilter
你也可以添加自己定义的filter,使用custom-filter元素来设定,并且使用上面所列的名字来指定其具体的位置
  <beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter">
    <custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
  </beans:bean>
在上面的position也可以设置为before或者after,来指定是插入到filter链的具体地方。FIRST和LAST是指整个链的最开始和最尾部。
Session定置攻击保护
如果你知道别人的session id,你就可以根据这个id来创建HTTP请求。当应用程序收到这样的请求时,它会认为这些请求是与原来那个用户相关联的,于是你就拥有了那个用户的权限。Spring Security能够很有效地对付这类型的Session攻击。其可以通过<http>下面设置session-fixation-protection来完成,该属性有3种选项:
migrateSession: 创建一个新的session,然后将旧的session里面的值拷贝到新的session里面去,这是默认的选项
none,就是啥都不做,保留旧的session
newSession,创建一个新的session,但是不从旧的session里面拷贝任何数据
设置一个自定义的AuthenticationEntryPoint
**暂时用不到**
方法安全
Spring Security 2.0增强了对服务层方法的安全的支持。如果你使用Java 5或者更高的版本,那么JSR-250的安全方面的注解以及该框架提供的@secured标识是可以使用的。你可以使用intercept-methods元素来修饰单独的一个bean来添加安全方面的功能,或者使用AspectJ类型的横切面(pointcuts)来对整个服务层的多个beans添加安全功能。
<global-method-security>元素
这个元素主要是用来启动基于注解的安全功能,以及添加横切面方面的声明。你可以只是定义一个<global-method-security>元素。下面的声明就是来增加对两种类型的注解的支持:
<global-method-security secured-annotations="enabled" jsr250-annotations="enabled"/>
使用protected-pointcut来添加安全切入点
protect-pointcut是功能非常强大的,只需要简单的声明就为很多的beans添加了安全方面的保护。下面就是一个简单的例子:
  <global-method-security>
    <protect-pointcut expression="execution(* com.mycompany.*Service.*(..))" access="ROLE_USER"/>
  </global-method-security>
这个例子就是告诉只有ROLE_USER角色的才能够调用下面的方法:在com.mycompany包下面的,class名字是以Service结尾的方法。如果URL符合要求的话,那么在横切面上最早符合的就是该方法的安全切入点。
intercept-methods bean的装饰器
<bean:bean id="target" class="com.mycompany.myapp.MyBean">
    <intercept-methods>
        <protect method="set*" access="ROLE_ADMIN" />
        <protect method="get*" access="ROLE_ADMIN,ROLE_USER" />
        <protect method="doSomething" access="ROLE_USER" />
    </intercept-methods>
</bean:bean>
intercept-methods为特定的bean添加安全方面的保护。
默认的AccessDecisionManager
这一节是假设你有一些Spring Security的访问控制的底层体系结构的知识。
当我们使用名词空间配置的时候,默认是有一个AccessDecisionManager自动注册的,然后基于intercept-url和pretect-pointcut声明为方法调用以及web的URL访问来进行决策的。默认的是使用AffirmativeBased AccessDecisionManager和RoleVoter以及AuthenticatedVoter。
自定义AccessionDecisionManager
可以通过accession-decision-manager-ref这个元素来定义其自定义的AccessionDecisionManager 如果是方法访问方面的,则为
  <global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">
    ...
  </global-method-security>
如果是web的URL则为
  <http access-decision-manager-ref="myAccessDecisionManagerBean">
    ...
  </http>
验证管理器(Authentication Manager)
我们已经知道在使用名词空间配置时候,自动注册了一个authentication manager。这是Spring Security的ProviderManager类的一个实例,如果你过去使用过该框架的话,你应该会对该类已经很了解了。
你有可能通过添加<custom-authentication-provider>元素为ProviderManager注册一个额外的AuthenticationProvider beans
  <bean id="casAuthenticationProvider"
      class="org.springframework.security.providers.cas.CasAuthenticationProvider">
    <security:custom-authentication-provider />
    ...
  </bean>
另外一个常用的就是定义定义AuthenticationManager,这是一个特殊的元素,允许为AuthenticationManager注册一个别名,这样就可以在你的应用程序上下文的其他的任何一个地方进行使用了。
  <security:authentication-manager alias="authenticationManager"/>
  <bean id="casProcessingFilter" class="org.springframework.security.ui.cas.CasProcessingFilter">
     <security:custom-filter position="CAS_PROCESSING_FILTER"/>
     <property name="authenticationManager" ref="authenticationManager"/>
     ...
  </bean>
5
3
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics