简体   繁体   中英

Spring Security login with UserDetailsService and Java config

I am trying to add login functionality with a database lookup with Spring Security, and I am really struggling. I want to look up the user by implementing the UserDetailsService interface. I have read a ton of documentation and Googled for hours, but I am still stuck. Most of the examples that I could find are using XML, so maybe my problems are related to converting those to Java configuration.

UserDetailsService

@Service
public class AccountServiceImpl implements AccountService { // AccountService implements UserDetailsService
    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        // The email variable is always ''

        List<GrantedAuthority> authList = new ArrayList<>();
        authList.add(new Role("ROLE_USER")); // Role implements GrantedAuthority

        return new User("test@example.com", "password", true, true, true, true, authList);
    }
}

Security config

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;

    @Autowired
    private AccountService accountService;


    @Override
    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        // This bean is required for using method security annotations
        return super.authenticationManager();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login/process")
                .failureUrl("/login?error=true")
                .defaultSuccessUrl("/", false)
                .and()
                //.userDetailsService(this.accountService)
                .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessHandler(this.logoutSuccessHandler)
                    .invalidateHttpSession(true)
                .and()
                // Permissions here
                .csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("test@example.com").password("password").roles("USER");
    }

    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                //.userDetailsService(this.accountService);
                .inMemoryAuthentication()
                .withUser("test@example.com").password("password").roles("USER").and()
                .withUser("admin").password("password").roles("USER", "ADMIN");
    }*/

    /*@Bean
    public DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(this.accountService);
        return provider;
    }*/
}

As you can see, there is a bunch of outcommented code, which are just some of the things I tried to make it work. I also tried with simple in-memory authentication, but that didn't work either.

login.jsp

<form action="/login/process" method="POST">
    <input name="j_username" id="j_username" type="text" />
    <input name="j_password" id="j_password" type="password" />

    <input type="submit" value="Login" />
</form>

Debug

DEBUG org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Request is to process authentication

DEBUG org.springframework.security.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider

DEBUG org.springframework.security.authentication.dao.DaoAuthenticationProvider - User '' not found

DEBUG org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials

DEBUG org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Updated SecurityContextHolder to contain null Authentication

The above seems to always be the case for all of the configurations that I tried. I am not even sure why the DaoAuthenticationProvider is used, even if I try to override it; I guess it's a default. For some of the configuration above, my UserDetailsService implementation gets called, but with an empty string as the parameter. Also, even if I return a hard coded UserDetails object with the same credentials as the ones I entered in my form, the authentication still fails, and I get redirected back to /login?error=true .

What am I doing wrong here? Please inform me about my mistakes or provide a simple example using Java configuration. Thanks!

When using Spring Security with Java based configuration the name of the request parameters are username and password and not j_username and j_password anymore.

You can either fix your login form

<form action="/login/process" method="POST">
    <input name="username" id="j_username" type="text" />
    <input name="password" id="j_password" type="password" />

    <input type="submit" value="Login" />
</form>

or adapt your configuration to use the old field names.

formLogin().usernameParameter("j_username").passwordParameter("j_password");

Either way will resolve your issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM