David Moreno García
David Moreno García

Reputation: 4523

Custom UserDetailsService not executing correctly

I'm trying to configure Spring Security but I have an extrange problem with my custom UserDetailsService. Everytime I try to login in I'm redirected to my failure page. This is the code of the service:

@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

    private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);

    @Autowired
    private UserService userService;

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

        logger.info("This is printed");

        UserDetails userDetails = userService.findOne(username);

        logger.info("This isn't printed");

        if (userDetails == null) {
            logger.info("This isn't printed");
            throw new UsernameNotFoundException("No user found with username "
                    + username);
        }

        return userDetails;
    }

}

As you can see in the code, some of the loggers are never printed and that is a little weird...

This are my User model, its repository and its service classes:

@Entity
public class User implements UserDetails {
    // more code


@Transactional(readOnly = true)
public interface UserRepository extends JpaRepository<User, Long> {

    User findByUsername(String username);
}

@Repository
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public List<User> findAll() {
        return userRepository.findAll();
    }

    @Override
    public User findOne(String username) {
        return userRepository.findByUsername(username);
    }

    @Override
    @Transactional
    public User save(User user) {
        return userRepository.save(user);
    }
}

My web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <!-- Spring Security filters -->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- This is used to inject webroot property (used by persistence.xml) -->
    <listener>
        <listener-class>com.leakedbits.twicker.listener.WebAppPropertiesListener</listener-class>
    </listener>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- The definition of the Root Spring Container shared by all Servlets 
        and Filters -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/security.xml
            /WEB-INF/spring/root-context.xml
        </param-value>
    </context-param>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Processes application requests -->
    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

My security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security 
        http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util-3.1.xsd">

    <http pattern="/resources" security="none" />

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/login" access="permitAll" />
        <intercept-url pattern="/logout" access="permitAll" />
        <intercept-url pattern="/denied" access="hasRole('ROLE_USER')" />
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/user" access="hasRole('ROLE_USER')" />
        <intercept-url pattern="/init2" access="hasRole('ROLE_ADMIN')" />
        <intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')" />

        <form-login login-page="/login" authentication-failure-url="/login/failure"
            default-target-url="/" />

        <access-denied-handler error-page="/denied" />

        <logout invalidate-session="true" logout-success-url="/logout/success"
            logout-url="/logout" />
    </http>

    <!-- This line must to be here because for some random reason the implementation 
        wasn't found without it -->
    <beans:bean id="customUserDetailsService"
        class="com.leakedbits.twicker.service.security.CustomUserDetailsService" />

    <authentication-manager>
        <authentication-provider user-service-ref="customUserDetailsService">
            <password-encoder hash="sha" />
        </authentication-provider>
    </authentication-manager>
</beans:beans>

Finally, the code that I run previously to add a test user:

User user = new User();
user.setPassword("7c4a8d09ca3762af61e59520943dc26494f8941b"); // 123456
user.setUsername("davidmogar");
Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
user.setGrantedAuthorities(grantedAuthorities);
userService.save(user);

What I'm doing wrong?

EDIT

For an unknown reason, userService is null so is not being autowired. I'm not sure which could be the problem. This service is working well inside the controller.

Upvotes: 0

Views: 1116

Answers (1)

Ralph
Ralph

Reputation: 120811

Add autowire="byType" to the xlm definition of the userDetailsService bean

And remove the service annotation from the class, else you would have two instances of it.

Upvotes: 1

Related Questions