spring security xml配置官方详解

来源:互联网 发布:图像分类算法 简单 编辑:程序博客网 时间:2024/06/05 16:00

6. Security Namespace Configuration

6.1 Introduction

自2.0版本的spring框架以来,命名空间配置已可用。 它允许您使用来自附加XML模式的元素来补充传统的Spring beans应用程序上下文语法。 您可以在Spring参考文档中找到更多信息。 命名空间元素可以简单地用于允许配置单个bean的更简洁的方式,或者更有力地定义更紧密地匹配问题域并且隐藏来自用户的底层复杂性的备选配置语法。 一个简单的元素可以隐藏多个bean和处理步骤被添加到应用程序上下文的事实。 例如,将以下元素从安全命名空间添加到应用程序上下文将启动嵌入式LDAP服务器,以便在应用程序中测试使用:

<security:ldap-server />

这比布线等效的Apache目录服务器bean要简单得多。 最常见的替代配置要求是由ldap-server元素上的属性支持的,并且用户不需要担心需要创建哪些bean以及bean属性名称。在编辑应用程序上下文文件时使用良好的XML编辑器应提供有关可用属性和元素的信息。我们建议您尝试Spring工具套件,因为它具有使用标准Spring命名空间的特殊功能。

要在应用程序上下文中开始使用安全命名空间,您需要在类路径上具有spring-security-config jar。 然后你需要做的是将模式声明添加到应用程序上下文文件中:

<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-3.0.xsd        http://www.springframework.org/schema/security        http://www.springframework.org/schema/security/spring-security.xsd">    ...</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在许多示例中,您将看到(在示例应用程序中),我们通常使用”security”作为默认命名空间,而不是”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-3.0.xsd        http://www.springframework.org/schema/security        http://www.springframework.org/schema/security/spring-security.xsd">    ...</beans:beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

我们将假设此语法从现在开始在本章中使用。

6.1.1 Design of the Namespace

命名空间旨在捕获框架的最常见用法,并提供简化和简洁的语法,以便在应用程序中启用它们。 该设计基于框架内的大规模依赖性,可以分为以下几个方面:

  • Web / HTTP安全 - 最复杂的部分。设置过滤器和相关服务bean,用于应用框架认证机制,安全URL,呈现登录和错误页面等等。
  • 业务对象(方法)安全 - 用于保护服务层的选项。
  • AuthenticationManager - 处理来自框架其他部分的认证请求。
  • AccessDecisionManager - 提供Web和方法安全的访问决策。默认的一个将被注册,但你也可以选择使用一个自定义的,使用正常的Spring bean语法声明。
  • AuthenticationProviders - 身份验证管理器对用户进行身份验证的机制。命名空间提供了对几个标准选项的支持,也是添加使用传统语法声明的自定义bean的方法
  • UserDetailsService - 与身份验证提供程序密切相关,但通常也需要其他bean。

我们将在以下部分了解如何配置这些。

6.2 Getting Started with Security Namespace Configuration

在本节中,我们将介绍如何构建命名空间配置以使用框架的一些主要功能。 让我们假设您最初想要尽快开始和运行,并向现有的Web应用程序添加身份验证支持和访问控制,并进行一些测试登录。 然后,我们将看看如何转换为对数据库或其他安全存储库进行身份验证。 在后面的部分,我们将介绍更多的高级命名空间配置选项。

6.2.1 web.xml Configuration

您需要做的第一件事是将以下过滤器声明添加到您的web.xml文件:

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这提供了一个到Spring Security Web基础结构的钩子。 DelegatingFilterProxy是一个Spring Framework类,它委托给一个过滤器实现,该过滤器实现在应用程序上下文中定义为一个Spring bean。 在这种情况下,bean名为springSecurityFilterChain,它是由命名空间创建的内部基础结构bean,用于处理Web安全。 注意,你不应该自己使用这个bean名称。 将它添加到web.xml后,就可以开始编辑应用程序上下文文件。 Web安全服务使用<http>元素配置。

6.2.2 A Minimal Configuration

启用Web安全所需的所有功能都是

<http><intercept-url pattern="/**" access="hasRole('USER')" /><form-login /><logout /></http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

其中说我们希望我们的应用程序中的所有URL是安全的,需要角色ROLE_USER来访问它们,我们想使用一个带有用户名和密码的表单登录应用程序,并且我们想要一个注销URL注册,这将允许我们注销应用程序。<http>元素是所有Web相关命名空间功能的父级。<intercept-url>元素定义了一个模式,使用ant路径样式语法,匹配传入请求的URL。您还可以使用正则表达式匹配作为替代(有关更多详细信息,请参阅命名空间附录)。访问属性定义与给定模式匹配的请求的访问要求。使用默认配置,这通常是逗号分隔的角色列表,其中一个用户必须允许提出请求。前缀”ROLE_”是指示应当与用户的权限进行简单比较的标记。换句话说,应该使用正常的基于角色的检查。 Spring Security中的访问控制不限于使用简单角色(因此使用前缀来区分不同类型的安全属性)。我们将在后面看到解释如何改变脚注:[访问属性中的逗号分隔值的解释取决于使用的-1-的实现。在Spring Security 3.0中,该属性也可以填充为-2-。]

您可以使用多个<intercept-url>元素为不同的网址集合定义不同的访问要求,但会按列出的顺序进行评估,并使用第一个匹配项。 所以你必须把最具体的比赛放在顶部。 您还可以添加方法属性来限制与特定HTTP方法(GET,POST,PUT等)的匹配。

要添加一些用户,可以直接在命名空间中定义一组测试数据:

<authentication-manager><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></authentication-manager>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

如果你熟悉框架的命名空间前版本,你可能已经猜到了这里发生了什么。 <http>元素负责创建FilterChainProxy和它使用的过滤器bean。 诸如不正确的滤波器排序的常见问题不再是问题,因为滤波器位置是预定义的。<authentication-provider>元素创建DaoAuthenticationProvider bean<user-service>元素创建InMemoryDaoImpl。 所有认证提供者元素必须是<authentication-manager>元素的子元素,它创建一个ProviderManager并向其注册认证提供者。 您可以找到有关在命名空间附录中创建的bean的更多详细信息。 如果你想开始了解框架中的重要类以及如何使用它们,这是值得交叉检查的,尤其是如果你想以后定制的东西。

上面的配置定义了两个用户,他们的密码和它们在应用程序中的角色(将用于访问控制)。 还可以使用user-service上的properties属性从标准属性文件加载用户信息。 有关文件格式的更多详细信息,请参阅内存中身份验证部分。 使用<authentication-provider>元素意味着用户信息将被认证管理器用来处理认证请求。 您可以有多个<authentication-provider>元素来定义不同的认证源,并依次咨询每个。 在这一点上,您应该能够启动您的应用程序,您将需要登录以继续。 尝试一下,或尝试使用项目附带的”教程”示例应用程序。

6.2.3 Form and Basic Login Options

您可能想知道当提示登录时登录表单来自哪里,因为我们没有提到任何HTML文件或JSP。 实际上,由于我们没有为登录页面显式设置URL,Spring Security会根据启用的功能自动生成一个URL,并使用处理提交的登录的URL的标准值,用户将使用的默认目标URL 在登录后发送到等等。 但是,命名空间提供了大量的支持,允许您自定义这些选项。 例如,如果您想提供自己的登录页面,可以使用:

<http><intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/><intercept-url pattern="/**" access="ROLE_USER" /><form-login login-page='/login.jsp'/></http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

还要注意,我们添加了一个额外的intercept-url元素来说明对匿名用户的任何登录页面的请求都应该可用,并且AuthenticatedVoter类可以获得关于如何处理值IS_AUTHENTICATED_ANONYMOUSLY的更多细节。 否则,请求将匹配模式/**,并且将无法访问登录页面本身! 这是一个常见的配置错误,并将导致应用程序中的无限循环。 如果您的登录页面显示为安全的,Spring Security将在日志中发出警告。 也可以通过为模式定义单独的http元素,使所有匹配特定模式的请求完全绕过安全过滤器链,如下所示:

<http pattern="/css/**" security="none"/><http pattern="/login.jsp*" security="none"/><http use-expressions="false"><intercept-url pattern="/**" access="ROLE_USER" /><form-login login-page='/login.jsp'/></http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

从Spring Security 3.1,现在可以使用多个http元素为不同的请求模式定义单独的安全过滤器链配置。 如果从http元素中省略pattern属性,则它匹配所有请求。 创建不安全模式是此语法的一个简单示例,其中模式映射到空过滤器链。 我们将在安全过滤器链的章节中更详细地讨论这个新的语法。 重要的是要意识到这些不安全的请求将完全忽略任何Spring Security Web相关的配置或其他属性,如requires-channel,所以您将无法访问当前用户的信息或在请求期间调用安全方法。 如果您仍希望应用安全过滤器链,请使用

access ='IS_AUTHENTICATED_ANONYMOUSLY'

如果要使用基本认证而不是表单登录,则将配置更改为

<http use-expressions="false"><intercept-url pattern="/**" access="ROLE_USER" /><http-basic /></http>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

然后,基本身份验证将优先,并且将用于在用户尝试访问受保护资源时提示登录。 如果您希望使用此配置,则表单登录仍然可用于此配置,例如通过嵌入在另一个网页中的登录表单。

Setting a Default Post-Login Destination

如果尝试访问受保护资源时未提示表单登录,则将使用default-target-url选项。 这是用户成功登录后将访问的URL,默认为”/”。 您还可以将always-use-default-target属性设置为”true”,以便用户始终在此页面结束(无论登录是“按需”还是他们明确选择登录) 。 如果应用程序始终要求用户在“主页”页面上启动,这是非常有用的,例如:

<http pattern="/login.htm*" security="none"/><http use-expressions="false"><intercept-url pattern='/**' access='ROLE_USER' /><form-login login-page='/login.htm' default-target-url='/home.htm'        always-use-default-target='true' /></http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

为了更好地控制目标,您可以使用authentication-success-handler-ref属性作为default-target-url的替代。 引用的bean应该是AuthenticationSuccessHandler的一个实例。 您可以在Core Filters章节以及命名空间附录中找到更多信息,以及有关如何在身份验证失败时自定义流的信息。

6.2.4 Logout Handling

注销元素通过导航到特定的URL添加了注销的支持。 默认注销URL是/logout,但是您可以使用logout-url属性将其设置为其他值。 关于其他可用属性的更多信息可以在命名空间附录中找到。

6.2.5 Using other Authentication Providers

实际上,您将需要一个更为可扩展的用户信息源,而不是添加到应用程序上下文文件中的几个名称。 很可能你会想要存储您的用户信息在类似数据库或LDAP服务器。 LDAP命名空间配置在LDAP章节中讨论,因此我们不在这里讨论。 如果您有一个Spring Security的UserDetailsService的自定义实现,在应用程序上下文中称为”myUserDetailsService”,那么您可以使用

<authentication-manager>    <authentication-provider user-service-ref='myUserDetailsService'/></authentication-manager>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

如果要使用数据库,那么可以使用

<authentication-manager><authentication-provider>    <jdbc-user-service data-source-ref="securityDataSource"/></authentication-provider></authentication-manager>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

其中”securityDataSource”是应用程序上下文中的DataSource bean的名称,指向包含标准Spring Security用户数据表的数据库。 或者,您可以配置Spring SecurityJdbcDaoImpl bean,并指向使用user-service-ref属性的bean:

<authentication-manager><authentication-provider user-service-ref='myUserDetailsService'/></authentication-manager><beans:bean id="myUserDetailsService"    class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl"><beans:property name="dataSource" ref="dataSource"/></beans:bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

您还可以使用标准AuthenticationProvider beans如下

<authentication-manager>    <authentication-provider ref='myAuthenticationProvider'/></authentication-manager>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

其中myAuthenticationProvider是应用程序上下文中实现AuthenticationProvider的bean的名称。 您可以使用多个authentication-provider元素,在这种情况下,将按声明它们的顺序查询提供程序。 有关如何使用命名空间配置Spring Security AuthenticationManager的更多信息,请参见第6.6节”身份验证管理器和命名空间”。

Adding a Password Encoder

密码应始终使用为此目的设计的安全散列算法(不是像SHA或MD5这样的标准算法)进行编码。 这由<password-encoder>元素支持。 使用bcrypt编码的密码,原始验证提供程序配置将如下所示:

<beans:bean name="bcryptEncoder"    class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/><authentication-manager><authentication-provider>    <password-encoder ref="bcryptEncoder"/>    <user-service>    <user name="jimi" password="d7e6351eaa13189a5a3641bab846c8e8c69ba39f"            authorities="ROLE_USER, ROLE_ADMIN" />    <user name="bob" password="4e7421b1b8765d8f9406d87e7cc6aa784c4ab97f"            authorities="ROLE_USER" />    </user-service></authentication-provider></authentication-manager>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Bcrypt是大多数情况下的不错选择,除非你有一个旧系统,迫使你使用不同的算法。 如果您使用简单的哈希算法,或者更糟的是存储纯文本密码,那么您应该考虑迁移到更安全的选项,如bcrypt。

6.3 Advanced Web Features

6.3.1 Remember-Me Authentication

有关remember-me命名空间配置的信息,请参阅单独的Remember-Me章节。

6.3.2 Adding HTTP/HTTPS Channel Security

如果您的应用程序同时支持HTTP和HTTPS,并且您需要只能通过HTTPS访问特定的URL,则可以直接使用<intercept-url>上的requires-channel属性来支持:

<http><intercept-url pattern="/secure/**" access="ROLE_USER" requires-channel="https"/><intercept-url pattern="/**" access="ROLE_USER" requires-channel="any"/>...</http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

配置了这个配置后,如果用户尝试使用HTTP访问与”/secure/**”模式匹配的任何内容,它们将首先被重定向到HTTPS URL [5]。 可用的选项为”http”,”https”或”any”。 使用值”any”表示可以使用HTTP或HTTPS。

如果您的应用程序使用非标准端口进行HTTP和/或HTTPS,您可以指定端口映射列表,如下所示:

<http>...<port-mappings>    <port-mapping http="9080" https="9443"/></port-mappings></http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

请注意,为了真正安全,应用程序不应该使用HTTP或在HTTP和HTTPS之间切换。 它应该以HTTPS(用户输入HTTPS URL)开始,并使用安全连接,以避免任何中间人攻击的可能性。

6.3.3 Session Management

Detecting Timeouts

您可以配置Spring Security以检测无效会话ID的提交,并将用户重定向到相应的URL。 这是通过session-management实现的:

<http>...<session-management invalid-session-url="/invalidSession.htm" /></http>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

请注意,如果您使用此机制检测会话超时,则可能会错误地报告错误,如果用户注销,然后重新登录,而不关闭浏览器。 这是因为会话cookie在会话失效时不会被清除,即使用户已注销,也将重新提交。 您可以在注销时显式删除JSESSIONID cookie,例如在注销处理程序中使用以下语法:

<http><logout delete-cookies="JSESSIONID" /></http>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

不幸的是,这不能保证与每个servlet容器一起工作,所以你需要在你的环境中测试它

如果您正在代理后运行应用程序,您还可以通过配置代理服务器来删除会话cookie。 例如,使用Apache HTTPD的mod_headers,以下指令将通过在对注销请求的响应中过期来删除JSESSIONID cookie(假设应用程序部署在路径/tutorial):

<LocationMatch "/tutorial/logout">始终 set Set-Cookie“JSESSIONID =; Path = / tutorial; Expires = Thu,01 Jan 1970 00:00:00 GMT”</ LocationMatch>
  • 1
  • 1

Concurrent Session Control

如果您希望限制单个用户登录到您的应用程序的能力,Spring Security支持这种开箱即用的简单添加功能。 首先,您需要将以下侦听器添加到web.xml文件中,以使Spring Security更新有关会话生命周期事件:

<listener><listener-class>    org.springframework.security.web.session.HttpSessionEventPublisher</listener-class></listener>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

然后将以下行添加到应用程序上下文中:

<http>...<session-management>    <concurrency-control max-sessions="1" /></session-management></http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这将阻止用户多次登录 - 第二次登录将导致第一次登录失效。通常,您希望防止第二次登录,在这种情况下您可以使用

<http>...<session-management>    <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" /></session-management></http>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

第二次登录将被拒绝。 “被拒绝”是指如果正在使用基于表单的登录,则用户将被发送到authentication-failure-url。如果第二认证通过另一非交互机制(例如”记住我”)发生,则将向客户端发送”未授权”(401)错误。 如果您想要使用错误页面,可以将属性session-authentication-error-url添加到会话管理元素。 如果您使用自定义的身份验证过滤器进行基于表单的登录,则必须显式配置并发会话控制支持。 更多详细信息可以在会话管理一章中找到。

Session Fixation Attack Protection

会话固定攻击是潜在的风险,其中恶意攻击者可能通过访问站点来创建会话,然后说服另一用户登录同一会话(通过发送包含会话标识符作为参数的链接,用于 例)。 Spring Security通过创建一个新的会话或者在用户登录时以其他方式更改会话ID来自动防止此情况。如果您不需要此保护或者与其他某些要求冲突,则可以使用session-fixation-protection属性<session-management>,其中有四个选项

  • none - 不要做任何事情。原始会话将保留。
  • newSession - 创建一个新的“干净”会话,而不复制现有的会话数据(Spring Security相关的属性仍将被复制)。
  • migrateSession - 创建新会话并将所有现有会话属性复制到新会话。这是Servlet 3.0或更早版本容器中的默认值。
  • changeSessionId - 不要创建新会话。而应使用由Servlet容器提供的会话固定保护 (HttpServletRequest#changeSessionId()). 此选项仅在Servlet 3.1(Java EE 7)和更高版本的容器中可用。在旧容器中指定它将导致异常。这是Servlet 3.1和更新的容器中的默认值。

当发生会话固定保护时,会导致在应用程序上下文中发布SessionFixationProtectionEvent。 如果使用changeSessionId,此保护还将导致通知任何javax.servlet.http.HttpSessionIdListener,因此如果您的代码侦听这两个事件,请谨慎使用。 有关其他信息,请参阅”session management”一章。

6.3.4 OpenID Support

命名空间支持OpenID登录,而不是正常的基于表单的登录,或者除了正常的基于表单的登录,还有一个简单的更改:

<http><intercept-url pattern="/**" access="ROLE_USER" /><openid-login /></http>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

然后,您应该向OpenID提供程序(例如myopenid.com)注册自己,并将用户信息添加到您的内存中<user-service>

<user name="http://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
  • 1
  • 1

您应该能够使用myopenid.com网站进行登录验证。 还可以通过在openid-login元素上设置user-service-ref属性来选择特定的UserDetailsService bean以使用OpenID。 有关详细信息,请参阅上一节有关身份验证提供程序。 请注意,我们从上述用户配置中省略了密码属性,因为这组用户数据仅用于加载用户的权限。 将在内部生成随机密码,从而防止您在配置中的其他位置意外将此用户数据用作身份验证来源。

Attribute Exchange

支持OpenID 属性交换。例如,以下配置将尝试从OpenID提供程序检索电子邮件和全名,以供应用程序使用:

<openid-login><attribute-exchange>    <openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/>    <openid-attribute name="name" type="http://axschema.org/namePerson"/></attribute-exchange></openid-login>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

每个OpenID属性的”type”是由特定模式(在本例中为http://axschema.org/)确定的URI。 如果必须检索属性以便成功认证,则可以设置required的属性。 支持的确切模式和属性将取决于您的OpenID提供程序。 属性值作为认证过程的一部分返回,然后可以使用以下代码访问:

OpenIDAuthenticationToken token =    (OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();List<OpenIDAttribute> attributes = token.getAttributes();
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

OpenIDAttribute包含属性类型和检索的值(或多值属性的情况下的值)。 我们将在技术概述一章中查看Spring Security核心组件,了解有关如何使用SecurityContextHolder类的更多信息。 如果您希望使用多个身份提供程序,也支持多个attribute-exchange配置。 您可以提供多个属性交换元素,在每个元素上使用identifier-matcher属性。 它包含将与用户提供的OpenID标识符匹配的正则表达式。 有关示例配置,请参阅代码库中的OpenID示例应用程序,为Google,Yahoo和MyOpenID提供程序提供不同的属性列表。

6.3.5 Response Headers

有关如何自定义标头元素的其他信息,请参阅参考的第20章“安全HTTP响应标头”部分。

6.3.6 Adding in Your Own Filters

如果你之前使用过Spring Security,你会知道框架维护一个过滤器链,以便应用它的服务。 您可能希望在特定位置的堆栈中添加您自己的过滤器,或者使用当前没有命名空间配置选项(例如CAS)的Spring Security过滤器。 或者,您可能希望使用标准命名空间过滤器的自定义版本,例如由<form-login>元素创建的UsernamePasswordAuthenticationFilter,利用一些通过明确使用bean可用的额外配置选项。 如何使用命名空间配置,因为过滤器链不直接暴露? 使用命名空间时,始终严格执行过滤器的顺序。 当创建应用程序上下文时,过滤器bean按命名空间处理代码进行排序,标准的Spring Security过滤器在命名空间中有一个别名和一个众所周知的位置。

在以前的版本中,排序是在应用程序上下文的后处理过程中创建过滤器实例之后进行的。 在版本3.0+中,排序现在在实例化类之前在bean元数据级别完成。 这对于如何将您自己的过滤器添加到堆栈有影响,因为在解析<http>元素期间必须知道整个过滤器列表,因此语法在3.0中略有变化。

创建过滤器的过滤器,别名和命名空间elements/attributes如表6.1“标准过滤器别名和顺序”所示。 过滤器按过滤器链中出现的顺序列出。

Table 6.1. Standard Filter Aliases and Ordering

AliasFilter ClassNamespace Element or AttributeCHANNEL_FILTERChannelProcessingFilterhttp/intercept-url@requires-channelSECURITY_CONTEXT_FILTERSecurityContextPersistenceFilterhttpCONCURRENT_SESSION_FILTERConcurrentSessionFiltersession-management/concurrency-controlHEADERS_FILTERHeaderWriterFilterhttp/headersCSRF_FILTERCsrfFilterhttp/csrfLOGOUT_FILTERLogoutFilter http/logout  X509_FILTERX509AuthenticationFilterhttp/x509PRE_AUTH_FILTERAbstractPreAuthenticatedProcessingFilter SubclassesN/ACAS_FILTERCasAuthenticationFilterN/AFORM_LOGIN_FILTERUsernamePasswordAuthenticationFilterhttp/form-loginBASIC_AUTH_FILTERBasicAuthenticationFilterhttp/http-basicSERVLET_API_SUPPORT_FILTERSecurityContextHolderAwareRequestFilterhttp/@servlet-api-provisionJAAS_API_SUPPORT_FILTERJaasApiIntegrationFilterhttp/@jaas-api-provisionREMEMBER_ME_FILTERRememberMeAuthenticationFilterhttp/remember-meANONYMOUS_FILTERAnonymousAuthenticationFilterhttp/anonymousSESSION_MANAGEMENT_FILTERSessionManagementFiltersession-managementEXCEPTION_TRANSLATION_FILTERExceptionTranslationFilterhttpFILTER_SECURITY_INTERCEPTORFilterSecurityInterceptorhttpSWITCH_USER_FILTERSwitchUserFilterN/A

您可以使用custom-filter元素和其中一个名称来指定您的过滤器应该出现的位置:

<http><custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" /></http><beans:bean id="myFilter" class="com.mycompany.MySpecialAuthenticationFilter"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

如果希望在堆栈中的另一个过滤器之前或之后插入过滤器,也可以使用afterbefore属性。 名称”FIRST”和”LAST”可以与position属性一起使用,表示您希望过滤器分别出现在整个堆栈之前或之后。

如果您插入的自定义过滤器可能占据与命名空间创建的其中一个标准过滤器相同的位置,那么重要的是不要错误地包括命名空间版本。 删除创建要替换其功能的过滤器的任何元素。 请注意,您不能替换使用<http>元素本身(SecurityContextPersistenceFilterExceptionTranslationFilterFilterSecurityInterceptor)创建的过滤器。 默认情况下会添加其他过滤器,但您可以禁用它们。 默认情况下会添加一个AnonymousAuthenticationFilter,除非您禁用了会话锁定保护,一个SessionManagementFilter也将被添加到过滤器链。

如果要替换需要认证入口点的命名空间过滤器(即认证过程是由未经认证的用户尝试访问安全资源所触发的),则还需要添加自定义入口点bean。

Setting a Custom AuthenticationEntryPoint

如果您不使用表单登录,OpenID或通过命名空间的基本认证,您可能想要使用传统的bean语法定义认证过滤器和入口点,并将它们链接到命名空间中,如我们刚才看到的。 可以使用<http>元素上的entry-point-ref属性设置相应的AuthenticationEntryPoint。 CAS示例应用程序是使用带命名空间的自定义bean的一个很好的示例,包括此语法。 如果您不熟悉身份验证入口点,将在技术概述一章中讨论。

6.4 Method Security

从2.0版本开始,Spring Security已经大大提高了对您的服务层方法添加安全性的支持。 它提供对JSR-250注释安全性以及框架的原始@Secured注释的支持。 从3.0,你也可以使用新的基于表达式的注释。 您可以将安全性应用于单个bean,使用intercept-methods元素装饰bean声明,也可以使用AspectJ样式切入点在整个服务层上保护多个bean。

6.4.1 The global-method-security Element

此元素用于在应用程序中启用基于注释的安全性(通过设置元素上的相应属性),并将安全点切分声明分组在整个应用程序上下文中。 您应该只声明一个<global-method-security>元素。 以下声明将支持Spring Security的@Secured

<global-method-security secured-annotations="enabled" />

向方法(在类或接口上)添加注释将相应地限制对该方法的访问。 Spring Security的原生注释支持为方法定义了一组属性。 这些将被传递给AccessDecisionManager,以便做出实际的决定:

public interface BankService {@Secured("IS_AUTHENTICATED_ANONYMOUSLY")public Account readAccount(Long id);@Secured("IS_AUTHENTICATED_ANONYMOUSLY")public Account[] findAccounts();@Secured("ROLE_TELLER")public Account post(Account account, double amount);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以使用启用对JSR-250注释的支持

<global-method-security jsr250-annotations="enabled" />

这些是基于标准的,允许应用简单的基于角色的约束,但没有Spring Security的本机注释。要使用新的基于表达式的语法,您将使用

<global-method-security pre-post-annotations="enabled" />

和等效的Java代码

public interface BankService {@PreAuthorize("isAnonymous()")public Account readAccount(Long id);@PreAuthorize("isAnonymous()")public Account[] findAccounts();@PreAuthorize("hasAuthority('ROLE_TELLER')")public Account post(Account account, double amount);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如果您需要定义简单的规则,而不是根据用户的权限列表检查角色名称,基于表达式的注释是一个不错的选择。

注释的方法将仅对被定义为Spring bean的实例(在启用方法安全性的相同应用程序上下文中)是安全的。 如果你想保护不是由Spring创建的实例(例如使用new操作符),那么你需要使用AspectJ。

您可以在同一个应用程序中启用多个类型的注释,但只有一个类型应该用于任何接口或类,否则行为将不会被明确定义。 如果找到适用于特定方法的两个注释,则只应用其中一个。

Adding Security Pointcuts using protect-pointcut

使用protect-pointcut切换特别强大,因为它允许您只使用一个简单的声明来应用安全性到许多bean。 考虑下面的例子:

<global-method-security><protect-pointcut expression="execution(* com.mycompany.*Service.*(..))"    access="ROLE_USER"/></global-method-security>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

这将保护在应用程序上下文中声明的bean的所有方法,其类位于com.mycompany包中,其类名以”Service”结尾。 只有具有ROLE_USER角色的用户才能调用这些方法。 与URL匹配一样,最具体的匹配必须在切入点列表中位于第一,因为将使用第一个匹配表达式。 安全注释优先于切入点。

6.5 The Default AccessDecisionManager

本节假设您对Spring Security中的访问控制的底层架构有一些了解。 如果你不能,你可以跳过它,以后再回来,因为这一节只是真正相关的人需要做一些自定义,以使用超过简单的基于角色的安全。 当您使用命名空间配置时,会为您自动注册AccessDecisionManager的默认实例,并将根据您在intercept-urlprotect-pointcut声明中指定的访问属性,用于为方法调用和Web URL访问做出访问决策 (如果使用注释安全方法,则在注释中)。 默认策略是使用带有RoleVoterAuthenticatedVoterAffirmativeBasedAccessDecisionManager。 您可以在授权章节中找到有关这些的更多信息。

6.5.1 Customizing the AccessDecisionManager

如果您需要使用更复杂的访问控制策略,那么很容易为方法和Web安全设置一个替代方案。 对于方法安全性,您可以通过将global-method-security上的access-decision-manager-ref属性设置为应用程序上下文中相应的AccessDecisionManager bean的ID来实现:

<global-method-security access-decision-manager-ref="myAccessDecisionManagerBean">...</global-method-security>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

Web安全的语法是相同的,但在http元素:

<http access-decision-manager-ref="myAccessDecisionManagerBean">...</http>
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

6.6 The Authentication Manager and the Namespace

在Spring Security中提供认证服务的主要接口是AuthenticationManager。 这通常是Spring Security的ProviderManager类的一个实例,如果您以前使用过该框架,您可能已经熟悉它了。 如果没有,将在技术概述一章中稍后介绍。 使用authentication-manager命名空间元素注册bean实例。 如果您通过命名空间使用HTTP或方法安全性,则不能使用自定义AuthenticationManager,但这不应该是一个问题,因为您可以完全控制所使用的AuthenticationProvider。 您可能想要使用ProviderManager注册其他AuthenticationProvider bean,您可以使用具有ref属性的<authentication-provider>元素来执行此操作,其中属性的值是要添加的提供程序bean的名称。 例如:

<authentication-manager><authentication-provider ref="casAuthenticationProvider"/></authentication-manager><bean id="casAuthenticationProvider"    class="org.springframework.security.cas.authentication.CasAuthenticationProvider">...</bean>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

另一个常见的要求是上下文中的另一个bean可能需要引用AuthenticationManager。您可以轻松地注册AuthenticationManager的别名,并在应用程序上下文中的其他位置使用此名称。

<security:authentication-manager alias="authenticationManager">...</security:authentication-manager><bean id="customizedFormLoginFilter"    class="com.somecompany.security.web.CustomFormLoginFilter"><property name="authenticationManager" ref="authenticationManager"/>...</bean>
0 0
原创粉丝点击