package com.ningdatech.carapi.user.security.auth;

import com.ningdatech.carapi.common.constant.CommonConstant;
import com.ningdatech.carapi.user.security.auth.handler.DefaultExpiredSessionStrategy;
import com.ningdatech.carapi.user.security.auth.password.UsernamePasswordAuthSecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Collections;

/**
 * @Author LiuXinXin
 * @Date 2020/7/28 4:14 下午
 * @Version 1.0
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthProperties authProperties;

    @Autowired
    private UsernamePasswordAuthSecurityConfig usernamePasswordAuthSecurityConfig;

    @Autowired
    @Qualifier(value = "defaultLogoutSuccessHandler")
    private LogoutSuccessHandler logoutSuccessHandler;

    @Autowired
    private DefaultExpiredSessionStrategy defaultExpiredSessionStrategy;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage(authProperties.getAuthRequireUrl())
                .and().apply(usernamePasswordAuthSecurityConfig)
                .and()
                .authorizeRequests().antMatchers(authProperties.getIgnoreAuthUrlsArray()).permitAll().anyRequest()
                .authenticated().and()
                // 防止固定会话攻击，Spring security的默认配置就是如此：
                // 登陆成功之后会创建一个新的会话，然后将旧的session信息复制到新的session中（客户端的sessionId变了）
                .sessionManagement().invalidSessionUrl(authProperties.getInvalidSessionUrl()).sessionFixation()
                .migrateSession()
                // .invalidSessionStrategy(defaultInvalidSessionStrategy)
                .maximumSessions(10)
                .maxSessionsPreventsLogin(true)
                .expiredSessionStrategy(defaultExpiredSessionStrategy)
                .and().and()
                .logout().logoutUrl(authProperties.getLogoutUrl()).logoutSuccessHandler(logoutSuccessHandler)
                .deleteCookies(CommonConstant.COOKIE_KEY)
                .and().headers().frameOptions().sameOrigin()
                // .and()
                // .cors().configurationSource(corsConfigurationSource())
                .and()
                // .csrf().disable();
                // 开启csrf验证，需要前端同步传入token
                //.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .csrf().csrfTokenRepository(new CookieCsrfTokenRepository())
                .ignoringAntMatchers(authProperties.getIgnoreCsrfUrlsArray());
        // http.anonymous().authenticationFilter(availableUserAuthenticationFilter);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
        corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
//        corsConfiguration.setAllowedOrigins(Collections.singletonList("*"));
        corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
        corsConfiguration.setMaxAge(3600L);
        corsConfiguration.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", corsConfiguration);
        http.cors().configurationSource(source);
    }

}
