Reputation: 3565
Using annotation and java configuration it is not quite clear to me how to register an overridden filter for spring security.
What I want to achieve is to do an auto login without showing a Login form since at that time the user will already be authenticated. Therefore will only be reading a header param and use spring security for authorization purposes.
This is a simplified version of what I'm trying to, and the Spring security works correctly, except for sometimes showing the login screen. Bootstrapping the BypassLoginFilter is all I need to get this going. Also read somewhere that http auto config should be off for this kind of behaviour, but not sure how to implement in pure java configuration.
SecurityWebApplicationInitializer.java
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer{
}
SecurityConfig .java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled=true, prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/*").permitAll()
.anyRequest().hasRole("USER").and()
.formLogin()
.permitAll();
http.addFilterBefore(new BypassLoginFilter(), LogoutFilter.class);
//.and().anonymous().disable();
}
@Override
@Autowired
protected void registerAuthentication(AuthenticationManagerBuilder auth) {
try {
auth.inMemoryAuthentication().withUser("user").password("password")
.roles("USER").and().withUser("admin").password("password")
.roles("USER", "ADMIN");
} catch (Exception e) {
e.printStackTrace();
}
}
}
BypassLoginFilter.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
public class BypassLoginFilter extends AbstractAuthenticationProcessingFilter{
private static String HEADER_IS_ADMIN = "isAdmin";
public BypassLoginFilter()
{
super("/*");
}
//Never gets executed
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException,
IOException, ServletException {
boolean isAdmin = Boolean.valueOf(request.getHeader(HEADER_IS_ADMIN));
PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken("","",getAuthorities(isAdmin));
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
return getAuthenticationManager().authenticate(authRequest);
}
private List<GrantedAuthority> getAuthorities(boolean isAdmin)
{
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
if(isAdmin){
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
return authorities;
}
}
Upvotes: 6
Views: 7999
Reputation: 530
You can try following approach. Let's say you have a YourUser
class which looks like that:
public class YourUser extends org.springframework.security.core.userdetails.User{
...
public String getStartPage(){ return "/userhomepage"; }
...
}
Then you need to declare authentication handler:
@Component
public class YourAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication.getPrincipal() instanceof YourUser) {
final YourUser user = (YourUser) authentication.getPrincipal();
return user.getStartPage();
}else {
return "/defaultPageForNonAuthenticatedUsers";
}
}
}
And use it in the security configuration:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// rest calls are ommited
http.successHandler(successHandler());
}
@Bean
public AuthenticationSuccessHandler successHandler() throws Exception {
return new YourAuthenticationSuccessHandler();
}
}
Upvotes: 1