Spring 安全 4 xml 配置 UserDetailsS​​ervice 身份验证不起作用

Spring Security 4 xml configuration UserDetailsService authentication not working

我知道这个问题被问过很多次,但任何答案都解决了我的问题。 我正在尝试使用 Spring Security 4 + Hibernate + Spring Data Jpa 实现自定义登录表单,但事情并不像我预期的那样有效。

当我使用内存中的凭据时一切正常,但我想改用我的数据库。

下面是主要代码:

Xml 安全配置。

    <beans:bean id="encodeurMotDePasse" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value="12" />
    </beans:bean>

    <security:http auto-config="true" create-session="never">
        <security:intercept-url pattern="/" access="permitAll" />
        <security:intercept-url pattern="/inscription**" access="hasRole('ADMIN') or hasRole('USER')" />
        <security:intercept-url pattern="/connexion**" access="hasRole('USER') or hasRole('USER')" />
        <security:intercept-url pattern="/test**" access="hasRole('ADMIN')" />
        <security:intercept-url pattern="/dba**" access="hasRole('ADMIN')" />
        <security:form-login login-page="/login.html"
                             username-parameter="identifiant" 
                             password-parameter="motDePasse"
                             authentication-failure-url="/login.html?error=t"/>

    </security:http>

    <beans:bean id="customUserDetailsService" class="com.app.security.CustomUserDetailsService"/>
     <security:authentication-manager >
        <security:authentication-provider user-service-ref ="customUserDetailsService">
             <security:password-encoder ref="encodeurMotDePasse" />
        </security:authentication-provider> 
    </security:authentication-manager>

UserDetailsS​​ervice 实现:

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private ServicesDAO service;

    @Override
    public UserDetails loadUserByUsername( String username ) throws UsernameNotFoundException {

    T_authentification userPrincipals = service.getAuthenticatePrincipal( username );

    if ( userPrincipals == null ) {
        System.out.println( "user inexistant" );
        throw new UsernameNotFoundException( "L'utilisateur n'a pas été trouvé" );
    } else {
        System.out.println( "user trouvé" );
    }

    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    for ( T_roles role : userPrincipals.getRoles() ) {
        System.out.println( " role dans userdetails service est :" + role.getRoleName() );
        authorities.add( new SimpleGrantedAuthority( role.getRoleName() ) );
    }

    // return new CustomUserDetails( userPrincipals );
    return new org.springframework.security.core.userdetails.User( userPrincipals.getUsername(), userPrincipals.getMotDePasse(), authorities );
 }
}

当我在控制器方法中测试代码时,所有凭据都从数据库中正确加载,我可以在控制台上打印它们。

另一个问题是当登录失败时,Spring安全性不会在控制台中发送任何调试消息来说明失败的原因。

编辑

这里是我的 log4j.xml,我按照配置操作,但是控制台中出现任何消​​息,文件也是空的。

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration PUBLIC  "-//APACHE//DTD LOG4J 1.2//EN"    "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">

    <appender name="Appender1" class="org.apache.log4j.ConsoleAppender">
        <param name="Threshold" value="debug" />
       <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="%-7p %d [%t] %c %x - %m%n"/>
       </layout>
    </appender>

  <appender name="SpringAppender" class="org.apache.log4j.FileAppender"> 
        <param name="file" value="C:/Log4j/Spring-details.log" /> 
        <param name="Threshold" value="debug" />
        <param name="append" value="true" /> 
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                value="%d{MM/dd/yyyy HH:mm:ss}  [%t]:%c{5}.%M()%L %m%n" />
        </layout>
    </appender>

    <appender name="Appender2" class="org.apache.log4j.FileAppender">
       <param name="File" value="C:/Log4j/app.log" />
       <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="%-7p %d [%t] %c %x - %m%n"/>
       </layout>
    </appender>

     <category name="org.springframework">
        <priority value="ALL" />
    </category>


    <category name="org.springframework">
        <priority value="debug" />
    </category>

    <category name="org.springframework.beans">
        <priority value="debug" />
    </category>

    <category name="org.springframework.security">
        <priority value="debug" />
    </category>

    <category
        name="org.springframework.beans.CachedIntrospectionResults">
        <priority value="debug" />
    </category>

    <category name="org.springframework.jdbc.core">
        <priority value="debug" />
    </category>

    <category name="org.springframework.transaction.support.TransactionSynchronizationManager">
        <priority value="debug" />
    </category>

    <logger name="org.springframework" additivity="false">
        <level value="DEBUG"/>
        <appender-ref ref="SpringAppender"/>
    </logger>

    <root>
     <!--         <priority value="INFO"/> -->
        <level value="DEBUG"/>
        <appender-ref ref="Appender1" />
        <appender-ref ref="SpringAppender" />
        <appender-ref ref="Appender2" />
    </root>
</log4j:configuration> 

EDIT2

当我尝试在 java class 中 @Autowire 这个 bean <beans:bean id="customUserDetailsService" class="com.app.security.CustomUserDetailsService"/> 时遇到了这个异常。

为什么会出现这个错误?

ERROR javax.enterprise.web.core - ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inscriptionController': Unsatisfied dependency expressed through field 'customUserDetailsService'; nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'customUserDetailsService' is expected to be of type 'com.app.security.CustomUserDetailsService' but was actually of type 'com.sun.proxy.$Proxy323' at org.apache.catalina.core.StandardContext.start(StandardContext.java:5985)

非常感谢您的澄清,抱歉我的英语不好。

我找到了这种奇怪行为的原因。

我想 spring 安全侦听器 org.springframework.security.web.session.HttpSessionEventPublisher 不与 servlet 调度程序共享相同的上下文。因此,安全部分无法访问 mvc 上下文中定义的所有 bean。

为了解决这个问题,我不得不在根上下文中添加 <context:component-scan base-package=....,因为这里定义的所有 bean 都可以随处访问。

我花了 2 周的时间才找到问题的原因:( !