Using StandardPasswordEncoder in SpringBoot

2019-03-01 05:09发布

问题:

I've generated a Spring Boot web application using Spring Initializer, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.

Technologies used:

Spring Boot 1.4.2.RELEASE, Spring 4.3.4.RELEASE, Thymeleaf 2.1.5.RELEASE, Tomcat Embed 8.5.6, Maven 3, Java 8

This is my security config class:

@Configuration
@EnableWebSecurity
@PropertySource("classpath:/config/app-${APP-KEY}.properties")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${securityConfig.formLogin.loginPage}")
    private String loginPage;

    @Bean
    public StandardPasswordEncoder encoder() {
        return new StandardPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .formLogin()
                .loginPage(loginPage)
                .permitAll()
                .loginProcessingUrl("/tdk/login")
                .failureUrl("/tdk/login?error=true")
                .defaultSuccessUrl("/events/list")
                .and()
            .exceptionHandling()
                .accessDeniedPage("/denied")
                .and()
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers("/mockup/**").permitAll()
                .antMatchers("/users/**").permitAll()
                .antMatchers("/books/**").permitAll()
                .antMatchers("/welcome/**").authenticated()
                .and()
            .logout()
                .permitAll()
                .logoutSuccessUrl("/index.html");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .passwordEncoder(new StandardPasswordEncoder())
                .withUser("test1").password("c1f02fa50809b7f715576198eda6466cd17f63404ae6eded7c22290b025baf3868bc8f785267d4ae").roles("ADMIN").and()
                .withUser("test2").password("test2").roles("USER").and()
                .withUser("test3").password("test3").roles("SUPERADMIN");
    }


    @Bean
    public  static PropertySourcesPlaceholderConfigurer propertyDefaultConfig() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

This is my Junit Tests that works properly

public class StandardPasswordEncoderTests {

    @Test
    public void getPasswordForTest1() {
        StandardPasswordEncoder encoder = new StandardPasswordEncoder();
        String password = "test1";

        assertTrue(
                encoder.matches(password, "c1f02fa50809b7f715576198eda6466cd17f63404ae6eded7c22290b025baf3868bc8f785267d4ae"));

    }
}

Here my login template

<form th:action="@{/tdk/login}" method="post">

            <p th:if="${param.error}">
                Bad Credentials  ${param.error}
            </p>

                <p th:if="${loginError}" class="error">Wrong user or password</p>

                <div class="input_label"><i class="fa fa-user"></i><input type="text" name="user" placeholder="User" /></div>
                <div class="input_label"><i class="fa fa-key"></i><input type="password" name="pass" placeholder="Password" /></div>                      
                <input type="submit" value="LOGIN" />
             </form>

But whatever I put:

test1 / c1f02fa50809b7f715576198eda6466cd17f63404ae6eded7c22290b025baf3868bc8f785267d4ae

or

test2 / test2 

I see the message Bad Credentials ${param.error} in the output of my template

回答1:

The parameter names for username and password in your login page are not matching the names in Spring Security configuration.

You could change the Spring Security configuration to use the parameter names from your login page. Or you could change the login page to use the default parameter names.

See FormLoginConfigurer#usernameParameter:

The HTTP parameter to look for the username when performing authentication. Default is "username".

and FormLoginConfigurer#passwordParameter:

The HTTP parameter to look for the password when performing authentication. Default is "password".

Your modified login page (with default parameter names):

<form th:action="@{/tdk/login}" method="post">
    <p th:if="${param.error}">
        Bad Credentials  ${param.error}
    </p>

    <p th:if="${loginError}" class="error">Wrong user or password</p>

    <div class="input_label">
         <i class="fa fa-user"></i>
         <input type="text" name="username" placeholder="User" />
    </div>
    <div class="input_label">
         <i class="fa fa-key"></i>
         <input type="password" name="password" placeholder="Password" />
    </div>                      
    <input type="submit" value="LOGIN" />
</form>