Spring Security using HTTP headers

2019-04-07 07:32发布

问题:

I am trying to add security to my Spring Boot application. My current application is using REST controllers and every time I get a GET or POST request I read the HTTP header to retrieve the user and password in order to validate them against the properties file I have all my users stored. I want to change this to using Spring Security and this is what I got so far:

public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/index.html").permitAll()
            .antMatchers("/swagger-ui.html").hasRole("ADMIN")
            .anyRequest().authenticated();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("admin").password("password").roles("ADMIN").build());
    }
}

How can I tell the configure method that the user credentials are to be retrieved from the header and not a login form?

回答1:

You should avoid using default org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter since it gets client supplied username and password from the parameters of your request and you really need to get them from the headers.

So, you should write a custom AuthenticationFilter extending referred UsernamePasswordAuthenticationFilter to change its behaviour to fit your requirements:

public class HeaderUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    /**
     * 
     */
    public HeaderUsernamePasswordAuthenticationFilter() {
        super();
        this.setFilterProcessesUrl("/**");
        this.setPostOnly(false);
    }

    /* (non-Javadoc)
     * @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainPassword(javax.servlet.http.HttpServletRequest)
     */
    @Override
    protected String obtainPassword(HttpServletRequest request) {
        return request.getHeader(this.getPasswordParameter());
    }

    /* (non-Javadoc)
     * @see org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#obtainUsername(javax.servlet.http.HttpServletRequest)
     */
    @Override
    protected String obtainUsername(HttpServletRequest request) {
        return request.getHeader(this.getPasswordParameter());
    }   

}

This filter example extends org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter listens to every request and gets username and password from headers instead of parameters.

Then you should change the configuration this way, setting your filter in the UsernamePasswordAuthenticationFilter position:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterAt(
                new HeaderUsernamePasswordAuthenticationFilter(), 
                UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers("/index.html").permitAll()
            .antMatchers("/swagger-ui.html").hasRole("ADMIN")
            .anyRequest().authenticated();
    }


回答2:

In memory authentication would serve your purpose

@Configuration
@EnableWebMvc
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
        .withUser("user1").password("password1").roles("USER")
        .and()
        .withUser("user2").password("password2").roles("ADMIN");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().fullyAuthenticated();
        http.httpBasic();   
    }

}


回答3:

In spring boot app you can add below to application.properties

security.user.name=user
security.user.password=password

It will do rest of the thing like getting it from header and validation for more visit https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-security.html