【问题标题】:Spring Security 3 not work with JDK 1.7Spring Security 3 不适用于 JDK 1.7
【发布时间】:2012-03-21 15:05:02
【问题描述】:

我在我的 Spring MVC 项目中使用带有 LDAP 身份验证的 Spring Security 3。 在我需要将我的项目部署到其他环境并将 JDK 的版本从 1.6 更改为 1.7 之前,它工作正常。

下面是我的 spring 安全配置文件和示例代码:

1) 安全应用程序上下文.xml

    <?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns:s="http://www.springframework.org/schema/security"
    xmlns="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-3.1.xsd">

    <s:http use-expressions="true">     
        <s:intercept-url pattern="/auth/**" access="permitAll" />
        <s:intercept-url pattern="/css/**" access="permitAll" />
        <s:intercept-url pattern="/image/**" access="permitAll" />
        <s:intercept-url pattern="/scripts/**" access="permitAll" />        

        <s:intercept-url pattern="/**" access="hasRole('GENERAL_USER')" />

        <s:form-login login-page="/auth/login.html" 
                      default-target-url="/welcome.html"  
                      authentication-failure-url="/auth/login.html?error=1" /> 

        <s:access-denied-handler error-page="/auth/denied.html"/>   

        <s:logout invalidate-session="true" logout-success-url="/auth/logoutSuccess.html"/>                         
    </s:http>

    <s:authentication-manager>
        <s:authentication-provider ref="ldapAuthProvider" />
    </s:authentication-manager>

    <bean 
        id="contextSource"
        class="org.springframework.security.ldap.DefaultSpringSecurityContextSource" 
        scope="singleton">
        <constructor-arg
            value="ldap://ldapurl:389/dc=o,dc=a"  />
            <property name="userDn" value="cn=xxx,cn=users,dc=o,dc=a" />
            <property name="password" value="password" />
            <property name="baseEnvironmentProperties">
                <map>
                    <entry key="java.naming.referral">
                        <value>follow</value>
                    </entry>                    
                </map>
            </property>         
    </bean>

    <bean id="userSearch"
        class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
        <!-- searchBase, searchFilter, contextSource -->
        <constructor-arg index="0" value="" />
        <constructor-arg index="1" value="(sAMAccountName={0})" />
        <constructor-arg index="2" ref="contextSource" />
    </bean> 

    <bean id="ldapAuthProvider"
        class="com.foo.auth.MyLdapAuthenticationProvider">      
        <constructor-arg>     
            <bean     
                class="com.foo.auth.MyLdapAuthenticator">
                <constructor-arg ref="contextSource" />
                <property name="userSearch">
                    <ref bean="userSearch" />
                </property>             
            </bean>
        </constructor-arg>
        <property name="authoritiesPopulator" ref="authoritiesPopulator" />
        <property name="userDetailsContextMapper" ref="userDetailsMapper" />
    </bean>  

    <bean id="authoritiesPopulator" class="com.foo.auth.MyLdapAuthoritiesPopulator">
        <constructor-arg ref="userService" />       
    </bean>     

    <bean id="userService" class="com.foo.auth.MyLdapUserDetailsService">   
        <constructor-arg ref="userSearch" />
        <property name="userDetailsMapper" ref="userDetailsMapper" />
    </bean> 
    <bean id="userDetailsMapper" class="com.foo.auth.MyUserDetailsContextMapper">                    
    </bean>         
</beans>

2) 登录成功后会将url重定向到welcome.jsp,在welcome.jsp中,我使用spring security taglib来获取登录用户的全名。 (为了测试,我使用主体来显示整个上下文信息):

<security:authentication property="principal"></security:authentication>    

使用JDK 1.6时,principal显示:

com.foo.auth.MyUserDetails@3e2d20ec:.........

我可以使用我的自定义 UserDetail 属性,例如 principal.fullName。 使用JDK 1.7时,principal显示:

 org.springframework.security.ldap.userdetails.LdapUserDetailsImpl@86dae957:... 

它没有得到我的自定义 UserDetail 对象。所以如果我使用 JDKk1.7,我无法正确获取 Spring 上下文。

这个问题花了我将近 1 周的时间才发现根本原因是 JDK 版本的问题 ;-(

有谁知道为什么 LDAP 的 Spring Security 在 JDK1.7 中不起作用?还是我错过了要配置的东西?

提前谢谢你!

【问题讨论】:

    标签: spring-security ldap java-7


    【解决方案1】:

    问题已解决。 这是因为我的 MyLdapAuthenticationProvider 扩展了错误的提供者。 我将 MyLdapAuthenticationProvider 扩展类更改为 LdapAuthenticationProvider, 并且 Spring Security 现在在 JDK 1.6 和 1.7 中都可以正常工作。

    这是我的自定义 LdapAuthenticationProvider:

    public class MyLdapAuthenticationProvider extends LdapAuthenticationProvider {
    
    private static Logger logger = Logger.getLogger(MyLdapAuthenticationProvider.class);         
    private MyLdapAuthenticator authenticator; 
    @Autowired
    private MyLdapAuthoritiesPopulator authoritiesPopulator;
    @Autowired
    private MyUserDetailsContextMapper userDetailsContextMapper;
    
    public MyLdapAuthenticationProvider(LdapAuthenticator authenticator) {
        super(authenticator);
        this.authenticator = (MyLdapAuthenticator) authenticator;
    }
    
    @Override
    protected DirContextOperations doAuthentication(UsernamePasswordAuthenticationToken userToken) {
        try {
            DirContextOperations dirCtx = getAuthenticator().authenticate(userToken);            
            return dirCtx;
        } catch (PasswordPolicyException ppe) {
            throw new LockedException(this.messages.getMessage(ppe.getStatus().getErrorCode(), ppe.getStatus()
                    .getDefaultMessage()));
        } catch (UsernameNotFoundException notFound) {            
            throw new BadCredentialsException("User Name Error!");
        } catch (NamingException ldapAccessFailure) {
            throw new AuthenticationServiceException(ldapAccessFailure.getMessage(), ldapAccessFailure);
        }
    }
    
    private void setAuthenticator(MyLdapAuthenticator authenticator) {
        Assert.notNull(authenticator, "An LdapAuthenticator must be supplied");
        this.authenticator = authenticator;
    }
    
    private MyLdapAuthenticator getAuthenticator() {
        return authenticator;
    }
    
    public MyUserDetailsContextMapper getUserDetailsContextMapper() {
        return userDetailsContextMapper;
    }
    
    public void setUserDetailsContextMapper(MyUserDetailsContextMapper userDetailsContextMapper) {
        this.userDetailsContextMapper = userDetailsContextMapper;
    }
    
    public void setAuthoritiesPopulator(MyLdapAuthoritiesPopulator authoritiesPopulator) {
        this.authoritiesPopulator = authoritiesPopulator;
    }
    
    public MyLdapAuthoritiesPopulator getAuthoritiesPopulator() {
        return authoritiesPopulator;
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-09
      • 2021-03-25
      • 2015-11-03
      • 2015-10-02
      • 1970-01-01
      • 2014-11-29
      • 1970-01-01
      • 2020-12-02
      相关资源
      最近更新 更多