001package org.woehlke.bloodmoney.config;
002
003import org.springframework.beans.factory.annotation.Autowired;
004import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
005import org.springframework.context.annotation.Bean;
006import org.springframework.context.annotation.Configuration;
007import org.springframework.context.annotation.Import;
008import org.springframework.data.web.config.EnableSpringDataWebSupport;
009import org.springframework.security.authentication.AuthenticationManager;
010import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
011import org.springframework.security.config.annotation.web.builders.HttpSecurity;
012import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
013import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
014import org.springframework.security.core.userdetails.UserDetailsService;
015import org.springframework.security.crypto.password.PasswordEncoder;
016import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
017import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
018import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
019import org.woehlke.bloodmoney.user.BloodMoneyUserAccountDetailsService;
020
021@Configuration
022@EnableWebSecurity
023@EnableSpringDataWebSupport
024@Import({
025    BloodMoneyWebMvcConfig.class
026})
027@EnableAutoConfiguration
028public class BloodMoneyWebSecurityConfig extends WebSecurityConfigurerAdapter {
029
030    @Override
031    protected void configure(HttpSecurity http) throws Exception {
032        http
033            .headers()
034            .disable()
035            .authorizeRequests()
036            .antMatchers(
037                this.bloodMoneyProperties.getWebSecurity().getAntMatchersPermitAll()
038            )
039            .permitAll()
040            .antMatchers(
041                this.bloodMoneyProperties.getWebSecurity().getAntMatchersFullyAuthenticated()
042            )
043            .fullyAuthenticated().anyRequest().authenticated()
044            .and()
045            .formLogin()
046            .loginPage(
047                this.bloodMoneyProperties.getWebSecurity().getLoginPage()
048            )
049            .usernameParameter(this.bloodMoneyProperties.getWebSecurity().getUsernameParameter())
050            .passwordParameter(this.bloodMoneyProperties.getWebSecurity().getPasswordParameter())
051            .loginProcessingUrl(this.bloodMoneyProperties.getWebSecurity().getLoginProcessingUrl())
052            .failureForwardUrl(this.bloodMoneyProperties.getWebSecurity().getFailureForwardUrl())
053            .defaultSuccessUrl(this.bloodMoneyProperties.getWebSecurity().getDefaultSuccessUrl())
054            .successHandler(this.authenticationSuccessHandler)
055            .permitAll()
056            .and()
057            .logout()
058            .logoutUrl(this.bloodMoneyProperties.getWebSecurity().getLogoutUrl())
059            .deleteCookies(this.bloodMoneyProperties.getWebSecurity().getDeleteCookies())
060            .invalidateHttpSession(this.bloodMoneyProperties.getWebSecurity().getInvalidateHttpSession())
061            .permitAll();
062    }
063
064    /**
065     * https://asecuritysite.com/encryption/PBKDF2z
066     * @return PasswordEncoder encoder
067     */
068    @Bean
069    public PasswordEncoder encoder(){
070        CharSequence secret=this.bloodMoneyProperties.getWebSecurity().getSecret();
071        int iterations=this.bloodMoneyProperties.getWebSecurity().getIterations();
072        int hashWidth=this.bloodMoneyProperties.getWebSecurity().getHashWidth();
073        Pbkdf2PasswordEncoder encoder = (new Pbkdf2PasswordEncoder(secret,iterations,hashWidth));
074        encoder.setEncodeHashAsBase64(true);
075        return encoder;
076    }
077
078    @Bean
079    public AuthenticationManager authenticationManager() throws Exception {
080        return this.authenticationManagerBuilder.userDetailsService(userAccountSecurityService).passwordEncoder(encoder()).and().build();
081    }
082
083    @Bean
084    public UsernamePasswordAuthenticationFilter authenticationFilter() throws Exception {
085        UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter();
086        filter.setAuthenticationManager(authenticationManager());
087        filter.setFilterProcessesUrl(this.bloodMoneyProperties.getWebSecurity().getLoginProcessingUrl());
088        return filter;
089    }
090
091    @Bean
092    public BloodMoneyWebMvcConfig mvcConfig(){
093        return this.mvcConfig;
094    }
095
096
097    private final AuthenticationManagerBuilder authenticationManagerBuilder;
098    private final AuthenticationSuccessHandler authenticationSuccessHandler;
099    private final UserDetailsService userAccountSecurityService;
100    private final BloodMoneyProperties bloodMoneyProperties;
101    private final BloodMoneyWebMvcConfig mvcConfig;
102
103    @Autowired
104    public BloodMoneyWebSecurityConfig(
105        AuthenticationManagerBuilder auth,
106        AuthenticationSuccessHandler authenticationSuccessHandler,
107        BloodMoneyUserAccountDetailsService bloodMoneyUserAccountDetailsService,
108        BloodMoneyProperties bloodMoneyProperties,
109        BloodMoneyWebMvcConfig bloodMoneyWebMvcConfig
110    ) {
111        this.authenticationManagerBuilder = auth;
112        this.authenticationSuccessHandler = authenticationSuccessHandler;
113        this.userAccountSecurityService = bloodMoneyUserAccountDetailsService;
114        this.bloodMoneyProperties = bloodMoneyProperties;
115        this.mvcConfig = bloodMoneyWebMvcConfig;
116    }
117
118}