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?
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();
}
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();
}
}
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