LDAP 通常被组织用作用户信息的中央存储库和身份验证服务。它还可以用于存储应用程序用户的角色信息。 对于如何配置 LDAP 服务器,存在许多不同的场景,因此 Spring Security 的 LDAP 提供程序是完全可配置的。它使用单独的策略接口进行身份验证和角色检索,并提供默认实现,这些实现可以被配置为处理各种各样的情况。 在尝试使用 Spring Security 之前,你应该熟悉 LDAP。以下链接很好地介绍了所涉及的概念以及使用免费 LDAP 服务器 OpenLDAP 建立目录的指南:http://www.zytrax.com/books/ldap/。熟悉从 Java 访问 LDAP 的 JNDI API 也可能是有用的。在 LDAP 提供程序中,我们不使用任何第三方 LDAP 库(Mozilla、JLDAP 等),但是 Spring LDAP 得到了广泛的使用,所以如果你打算添加自己的定制,那么熟悉该项目可能会很有用。 在使用 LDAP 认证时,确保正确配置 LDAP 连接池是很重要的。如果不熟悉如何做到这一点,可以参考 Java LDAP 文档。 LDAP 认证在 Spring Security 中大致可分为以下几个阶段。
例外情况是 LDAP 目录刚刚被用于检索用户信息并在本地对其进行身份验证。这可能是不可能的,因为目录通常设置有有限的读取访问属性,如用户密码。 我们将在下面查看一些配置方案。有关可用配置选项的完整信息,请参阅安全命名空间模式(XML 编辑器中应该提供安全命名空间模式的信息)。
你需要做的第一件事是配置应该进行身份验证的服务器。这是使用安全命名空间中的 <ldap-server url="ldap://springframework.org:389/dc=springframework,dc=org" />
也可以使用 <ldap-server root="dc=springframework,dc=org"/>
这里我们指定目录的根目录应该是 "dc=springframework,dc=org",这是默认的。使用这种方式,命名空间解析器将创建一个嵌入式 Apache 目录服务器,并扫描类路径以查找任何 LDIF 文件,它将尝试将其加载到服务器中。可以使用 <ldap-server ldif="classpath:users.ldif" /> 这使得用 LDAP 启动和运行更加容易,因为与外部服务器一起工作会很不方便。它还将用户隔离为连接 Apache 目录服务器所需的复杂 bean 配置。使用普通的 bean,配置会更加混乱。你必须具有可供应用程序使用的必要 Apache 目录依赖项 jar。这些可以从 LDAP 示例应用程序中获得。 这是最常见的 LDAP 认证方案。 <ldap-authentication-provider user-dn-pattern="uid={0},ou=people"/> 这个简单的示例将通过在所提供的模式中替换用户登录名并尝试使用登录密码绑定作为该用户,从而获得用户的DN。如果所有用户都存储在目录中的单个节点之下,这是可以的。如果你希望配置 LDAP 搜索过滤器来定位用户,则可以使用以下内容: <ldap-authentication-provider user-search-filter="(uid={0})" user-search-base="ou=people"/>
如果与上面的服务器定义一起使用,则这将使用 如何从 LDAP 目录中加载组的权限是由以下属性控制的。
因此,如果我们使用以下配置 <ldap-authentication-provider user-dn-pattern="uid={0},ou=people" group-search-base="ou=groups" />
并且被成功认证为用户 "ben",随后的权限加载将在目录条目 上面我们使用的名称空间配置选项使用起来很简单,并且比显式地使用 Spring bean 更简洁。有些情况下,你可能需要知道如何在应用程序上下文中直接配置 Spring Security LDAP。例如,你可能希望自定义某些类的行为。如果你很高兴使用命名空间配置,那么你可以跳过这一部分和下一个部分。
主要的 LDAP 提供程序类, 认证器还负责检索所需的用户属性。这是因为属性的权限可能取决于所使用的身份验证的类型。例如,如果绑定为用户,则可能需要使用用户自己的权限来读取它们。 目前有两种提供 Spring Security 的认证策略:
在能够(通过任一策略)对用户进行认证之前,必须从提供给应用程序的登录名获得区分名称(DN)。这可以通过简单的模式匹配(通过设置
包
上面讨论的 bean 必须能够连接到服务器。它们都必须提供一个
通常需要比简单的 DN 匹配更复杂的策略来定位目录中的用户条目。这可以封装在
该 bean 使用 LDAP 过滤器来匹配目录中的用户对象。该过程在 JDK DirContext 类 的 Javadoc 中对相应搜索方法进行了解释。正如在这里所解释的,搜索过滤器可以提供参数。对于这个类,唯一有效的参数是
在成功认证用户之后, 如果只希望使用 LDAP 进行身份验证,但是从差异源(例如数据库)加载权限,则可以提供此接口的自己的实现并注入该接口。 一个典型的配置,使用我们讨论过的一些 bean,可能是这样的: <bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> <constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/> <property name="userDn" value="cn=manager,dc=springframework,dc=org"/> <property name="password" value="password"/> </bean> <bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider"> <constructor-arg> <bean class="org.springframework.security.ldap.authentication.BindAuthenticator"> <constructor-arg ref="contextSource"/> <property name="userDnPatterns"> <list><value>uid={0},ou=people</value></list> </property> </bean> </constructor-arg> <constructor-arg> <bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"> <constructor-arg ref="contextSource"/> <constructor-arg value="ou=groups"/> <property name="groupRoleAttribute" value="ou"/> </bean> </constructor-arg> </bean>
这将建立一个提供访问 LDAP 服务器的提供者,使用 URL
要配置用户搜索对象,该对象使用过滤器 <bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"> <constructor-arg index="0" value=""/> <constructor-arg index="1" value="(uid={0})"/> <constructor-arg index="2" ref="contextSource" /> </bean>
并通过设置
使用 public interface UserDetailsContextMapper { UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authorities); void mapUserToContext(UserDetails user, DirContextAdapter ctx); }
只有第一个方法与认证相关。如果提供此接口的实现并将其注入
加载上下文数据的方式略有不同,这取决于你使用的认证类型。使用
激活的目录支持自己的非标准身份验证选项,并且正常使用模式与标准
配置 <bean id="adAuthenticationProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider"> <constructor-arg value="mydomain.com" /> <constructor-arg value="ldap://adserver.mydomain.com/" /> </bean> }
注意,不需要指定单独的
默认情况下,用户权限是从用户条目的 |