Spring Security + LDAP中的预身份验证

时间:2014-04-30 08:48:26

标签: java spring authentication spring-security

这是我想要实现的目标:

我正在使用Websphere,我想依靠容器进行身份验证(使用Kerberos + SPNEGO)。当涉及到Spring Security时,我希望依赖于预身份验证,并使用LDAP来检索用户详细信息(角色等)以进行授权检查。

这是Spring app上下文配置的一部分(试图只包含相关部分)

<s:global-method-security secured-annotations="enabled" pre-post-annotations="enabled" proxy-target-class="true" />

<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
    <s:filter-chain-map path-type="ant">
        <s:filter-chain pattern="/**"
            filters="securityContextPersistenceFilter,preAuthenticatedFilter" />
    </s:filter-chain-map>
</bean>


<s:http use-expressions="true" create-session="stateless" auto-config="true">
<!--
    <s:http-basic />
-->
</s:http>

<bean id="securityContextPersistenceFilter" 
        class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <property name='securityContextRepository'>
        <bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
            <property name='allowSessionCreation' value='true' />
        </bean>
    </property>
</bean>


<bean id="preAuthenticatedFilter"
        class="org.springframework.security.web.authentication.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

<s:authentication-manager alias="authenticationManager">
    <s:authentication-provider ref="preAuthenticatedAuthenticationProvider"   />
</s:authentication-manager>

<bean id="preAuthenticatedAuthenticationProvider" 
        class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService" >
        <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper" >
            <property name="userDetailsService" ref="userDetailsService" />
        </bean>
    </property>
</bean>


<bean id="userDetailsService" class="org.springframework.security.ldap.userdetails.LdapUserDetailsService" >
    <constructor-arg index="0" ref="ldapUserSearch"/>
    <constructor-arg index="1" ref="ldapAuthoritiesPopulator"/>
    <property name="userDetailsMapper" >
        <bean class="com.foo.MyUserDetailsMapper" />
    </property>
</bean>

<bean id="ldapContextSource"
    class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <!-- some setting skipped here -->
</bean>

<bean id="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <!-- some setting skipped here -->
</bean>

<bean id="ldapAuthoritiesPopulator"
    class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
    <!-- some setting skipped here -->
</bean>

<bean id="ldapTemplate" class="org.springframework.ldap.core.simple.SimpleLdapTemplate">
    <constructor-arg ref="ldapContextSource" />
</bean>

它主要起作用,我可以看到来自LDAP的自定义UserDetailsMapper(com.foo.MyUserDetailsMapper)的正确用户名和角色,在里面我将返回一个新的UserDetails更新角色。

问题是,在我的控制器中,当我尝试

SecurityContextHolder.getContext().getAuthentication()

它返回null。 (在我更改为预认证之前有效)

我错过了什么吗?

1 个答案:

答案 0 :(得分:7)

发现问题。抱歉,这主要是因为我自己的实现错误,这在问题本身中是看不到的。

我的自定义UserDetails impl错误地getEnabled()返回false。在LdapAuthenticationProvider中,它正常工作,因为没有检查用户状态。

但是,在PreAuthenticatedAuthenticationProvider中,默认情况下会有一个UserDetailsChecker来检查用户的状态,getEnabled()返回false会导致用户详细信息检查失败默默地,并导致身份验证未填充到SecurityContext(即将该帐户视为未经过身份验证)

虽然这主要是我的实施问题,但我认为仍然值得留在这里作为LdapAuthenticationProviderPreAuthenticatedAuthenticationProvider的差异的参考