/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.ui.config;
import java.util.Collections;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
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.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
/**
* Class containing all security methods and beans.
*
* @author Arnaldo Piccinelli
*/
@Configuration
@EnableWebSecurity
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MultiHttpSecurityConfig {
private static final String[] UNSECURED_RESOURCE_LIST = new String[] { "/resources/**", "/assets/**", "/css/**",
"/webjars/**", "/images/**", "/dandelion/**", "/js/**" };
private static final String[] UNAUTHORIZED_RESOURCE_LIST = new String[] { "/test.html", "/", "/unauthorized*",
"/error*", "/users*", "/accessDenied" };
@Configuration
@Profile({ "dev" })
protected static class InMemoryPersistentTokenRememberMeSetup {
@Value("${rememberMeToken}")
private String rememberMeToken;
@Value("${rememberMeParameter}")
private String rememberMeParameter;
@Bean
public RememberMeServices getRememberMeServices() {
PersistentTokenBasedRememberMeServices services = new PersistentTokenBasedRememberMeServices(
rememberMeToken, new BasicRememberMeUserDetailsService(), new InMemoryTokenRepositoryImpl());
services.setParameter(rememberMeParameter);
return services;
}
public class BasicRememberMeUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new User(username, "", Collections.<GrantedAuthority> emptyList());
}
}
}
@Configuration
@Profile({ "test", "live" })
protected static class JdbcPersistentTokenRememberMeSetup {
@Value("${rememberMeToken}")
private String rememberMeToken;
@Value("${rememberMeParameter}")
private String rememberMeParameter;
@Autowired
private DataSource dataSource;
@Bean
public RememberMeServices getRememberMeServices() {
JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager();
jdbcUserDetailsManager.setDataSource(dataSource);
JdbcTokenRepositoryImpl jdbcTokenRepositoryImpl = new JdbcTokenRepositoryImpl();
jdbcTokenRepositoryImpl.setDataSource(dataSource);
PersistentTokenBasedRememberMeServices services = new PersistentTokenBasedRememberMeServices(
rememberMeToken, jdbcUserDetailsManager, jdbcTokenRepositoryImpl);
services.setParameter(rememberMeParameter);
return services;
}
}
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
protected static class ExternalAuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
//@formatter:off
String authoritiesByUsernameQuery = "select username, authority from user_authorities " +
"inner join users on user_authorities.user_id = users.id " +
"inner join authorities on user_authorities.authority_id = authorities.id " +
"where username = ?";
JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
userDetailsService.setDataSource(dataSource);
userDetailsService.setAuthoritiesByUsernameQuery(authoritiesByUsernameQuery);
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder)
.and()
.jdbcAuthentication()
.authoritiesByUsernameQuery(authoritiesByUsernameQuery)
.passwordEncoder(passwordEncoder)
.dataSource(dataSource)
;
//@formatter:on
}
}
@Configuration
@Order(1)
@Profile({ "live" })
public static class LiveWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Value("${rememberMeToken}")
private String rememberMeToken;
@Value("${spring.profiles.active}")
private String activeProfile;
@Autowired
RememberMeServices rememberMeServices;
@Override
public void configure(WebSecurity web) throws Exception {
//@formatter:off
web
.ignoring()
.antMatchers(UNSECURED_RESOURCE_LIST);
//@formatter:on
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//@formatter:off
http
.headers()
.frameOptions()
.sameOrigin()
.and()
.authorizeRequests()
.antMatchers(UNAUTHORIZED_RESOURCE_LIST)
.permitAll()
.antMatchers("/git", "/manage", "/manage/**")
.hasRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.headers()
.cacheControl()
.and()
.frameOptions()
.deny()
.and()
.exceptionHandling()
.accessDeniedPage("/access?error")
.and()
.rememberMe()
.useSecureCookie(true)
.tokenValiditySeconds(60 * 60 * 24 * 10) // 10 days
.rememberMeServices(rememberMeServices)
.key(rememberMeToken)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/?logout")
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired");
// @formatter:on
}
}
@Configuration
@Order(1)
@Profile({ "dev", "test" })
public static class NonLiveWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Value("${rememberMeToken}")
private String rememberMeToken;
@Value("${spring.profiles.active}")
private String activeProfile;
@Autowired
RememberMeServices rememberMeServices;
@Override
public void configure(WebSecurity web) throws Exception {
//@formatter:off
web
.ignoring()
.antMatchers(UNSECURED_RESOURCE_LIST);
//@formatter:on
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//@formatter:off
http
.headers()
.frameOptions()
.sameOrigin()
.and()
.authorizeRequests()
.antMatchers(UNAUTHORIZED_RESOURCE_LIST)
.permitAll()
.antMatchers("/git", "/manage", "/manage/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.headers()
.cacheControl()
.and()
.frameOptions()
.deny()
.and()
.exceptionHandling()
.accessDeniedPage("/access?error")
.and()
.rememberMe()
.useSecureCookie(true)
.tokenValiditySeconds(60 * 60 * 24 * 10) // 10 days
.rememberMeServices(rememberMeServices)
.key(rememberMeToken)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/?logout")
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired");
// @formatter:on
}
}
// Register HttpSessionEventPublisher
@Bean
public static ServletListenerRegistrationBean<HttpSessionEventPublisher> httpSessionEventPublisher() {
return new ServletListenerRegistrationBean<HttpSessionEventPublisher>(new HttpSessionEventPublisher());
}
}