这是我想要实现的目标:
我正在使用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。 (在我更改为预认证之前有效)
我错过了什么吗?
答案 0 :(得分:7)
发现问题。抱歉,这主要是因为我自己的实现错误,这在问题本身中是看不到的。
我的自定义UserDetails
impl错误地getEnabled()
返回false
。在LdapAuthenticationProvider
中,它正常工作,因为没有检查用户状态。
但是,在PreAuthenticatedAuthenticationProvider
中,默认情况下会有一个UserDetailsChecker
来检查用户的状态,getEnabled()
返回false
会导致用户详细信息检查失败默默地,并导致身份验证未填充到SecurityContext
(即将该帐户视为未经过身份验证)
虽然这主要是我的实施问题,但我认为仍然值得留在这里作为LdapAuthenticationProvider
和PreAuthenticatedAuthenticationProvider
的差异的参考