/*
* Copyright (c) 2015. Bearchoke
*/
package com.bearchoke.platform.server.common.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.bearchoke.platform.server.common.security.ApiAuthenticationFailureHandler;
import com.bearchoke.platform.server.common.security.ApiAuthenticationSuccessHandler;
import com.bearchoke.platform.server.common.security.ApiRequestHeaderAuthenticationFilter;
import com.bearchoke.platform.server.common.security.UnauthorizedEntryPoint;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.inject.Inject;
import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Bjorn Harvold
* Date: 1/7/14
* Time: 9:44 PM
* Responsibility:
*/
@Configuration
@EnableWebSecurity
@Log4j2
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String USERNAME = "username";
private static final String PASSWORD = "password";
private static final String API_ADMINISTRATION_URL = "/api/administration/**";
private static final String API_MANAGER_URL = "/api/manager/**";
private static final String API_USER_URL = "/api/secured/**";
private static final String WEBSOCKET_URL = "/ws/*";
private static final String API_LOGIN_URL = "/api/authenticate";
private static final String API_PUBLIC_URL = "/*";
@Inject
private ApiAuthenticationSuccessHandler apiAuthenticationSuccessHandler;
@Inject
private ApiAuthenticationFailureHandler apiAuthenticationFailureHandler;
@Inject
@Qualifier("authenticationProvider")
private AuthenticationProvider authenticationProvider;
@Inject
@Qualifier("preAuthAuthenticationManager")
private AuthenticationManager preAuthAuthenticationManager;
@Inject
private ObjectMapper objectMapper;
/**
* Commons url security strategy
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
log.info("Configuring springSecurityFilterChain...");
// header details
http
.headers()
.frameOptions()
.sameOrigin()
.cacheControl()
.and().xssProtection()
.and().contentTypeOptions()
.and().httpStrictTransportSecurity();
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// the url patterns to secure
http
.authorizeRequests()
.antMatchers(API_ADMINISTRATION_URL).hasRole("ADMIN")
.antMatchers(API_MANAGER_URL).hasRole("MANAGER")
.antMatchers(API_USER_URL).hasRole("USER")
.antMatchers(API_LOGIN_URL).anonymous()
.antMatchers(API_PUBLIC_URL).permitAll()
;
// new logout handler from spring 4.0.2 - maybe nice to have. Has not been tested yet.
// HttpStatusReturningLogoutSuccessHandler logoutHandler = new HttpStatusReturningLogoutSuccessHandler();
// http
// .logout().logoutSuccessHandler(logoutHandler);
// filter details
http
.addFilterAfter(authFilter(), ApiRequestHeaderAuthenticationFilter.class)
.addFilter(preAuthFilter());
http
.csrf().disable();
http
.exceptionHandling().authenticationEntryPoint(new UnauthorizedEntryPoint(objectMapper));
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.GET, "/resources/*");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
@Bean(name = "authFilter")
public Filter authFilter() throws Exception {
log.info("Creating authFilter...");
RequestMatcher antReqMatch = new AntPathRequestMatcher(API_LOGIN_URL);
List<RequestMatcher> reqMatches = new ArrayList<>();
reqMatches.add(antReqMatch);
RequestMatcher reqMatch = new AndRequestMatcher(reqMatches);
UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter();
filter.setPostOnly(true);
filter.setUsernameParameter(USERNAME);
filter.setPasswordParameter(PASSWORD);
filter.setRequiresAuthenticationRequestMatcher(reqMatch);
filter.setAuthenticationSuccessHandler(apiAuthenticationSuccessHandler);
filter.setAuthenticationFailureHandler(apiAuthenticationFailureHandler);
filter.setAuthenticationManager(authenticationManager());
return filter;
}
@Bean(name = "preAuthFilter")
public Filter preAuthFilter() {
log.info("Creating preAuthFilter...");
ApiRequestHeaderAuthenticationFilter filter = new ApiRequestHeaderAuthenticationFilter();
filter.setAuthenticationManager(preAuthAuthenticationManager);
return filter;
}
//
// @Bean
// public AccessDecisionManager accessDecisionManager() {
// List<AccessDecisionVoter> voters = new ArrayList<>(1);
//// voters.add(new RoleVoter());
//// voters.add(new AuthenticatedVoter());
// voters.add(new WebExpressionVoter());
//
// AffirmativeBased ab = new AffirmativeBased(voters);
// ab.setAllowIfAllAbstainDecisions(true);
//
// return ab;
// }
}