Spring Security 3 не работает с JDK 1.7 - PullRequest
0 голосов
/ 20 марта 2012

Я использую Spring Security 3 с аутентификацией LDAP в моем проекте Spring MVC. Он работает нормально, пока мне не нужно развернуть свой проект в другой среде и изменить версию JDK с 1.6 на 1.7.

ниже - мой конфигурационный файл безопасности и пример кода:

1) security-application-Context.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, основной показывает:

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

и я могу использовать атрибут моего пользовательского UserDetail, такой как Principal.fullName. при использовании JDK 1.7, основной показывает:

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

он не получает мой пользовательский объект UserDetail. поэтому, если я использую JDKk1.7, я не могу правильно получить контекст Spring.

Эта проблема занимает у меня почти 1 неделю, чтобы выяснить причину проблемы JDK; - (

Кто-нибудь знает, почему Spring Security с LDAP не работает в JDK1.7? или я что-то упустил для настройки?

заранее спасибо!

1 Ответ

1 голос
/ 21 марта 2012

Проблема исправлена.Это потому, что мой MyLdapAuthenticationProvider расширяет неправильный поставщик.Я изменяю расширенный класс MyLdapAuthenticationProvider на LdapAuthenticationProvider, и теперь весенняя защита работает нормально как в 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;
}

}

...