Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security using HTTP headers

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?

like image 871
Chayma Atallah Avatar asked May 22 '17 10:05

Chayma Atallah


1 Answers

the minimal code addition is to define a filter and add it to the security configuration, smth like

XHeaderAuthenticationFilter.java

@Component
public class XHeaderAuthenticationFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    String xAuth = request.getHeader("X-Authorization");

    User user = findByToken(xAuth);

    if (user == null) {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token invalid");
    } else {
        final UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);

        filterChain.doFilter(request, response);
    }
}

//need to implement db user validation...
private User findByToken(String token) {
    if (!token.equals("1234"))
        return null;

    final User user = new User(
            "username",
            "password",
            true,
            true,
            true,
            true,
            Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));

    return user;
}
}

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .csrf().disable()
            .authorizeRequests().anyRequest().authenticated()
            .and()
            .exceptionHandling()
                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
            .and()
            .addFilterBefore(new XHeaderAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}

another approach is to use spring's AOP to define annotation of some logic to perform before entering the annotated controller method

like image 129
shahaf Avatar answered Sep 18 '22 09:09

shahaf