package com.enterprise.manage.core.secure;

import com.enterprise.manage.core.secure.domain.SecureUserService;
import com.enterprise.manage.core.secure.process.*;
import com.enterprise.manage.core.secure.support.SecureCaptchaSupport;
import com.enterprise.manage.core.secure.support.SecurePermissionSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/**
 * spring security 配置类
 *
 * @author PeiZhi Guo
 * 2021-2-19 10:03
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Resource
    private SecureUserService securityUserService;

    @Resource
    private SecureCaptchaSupport securityCaptchaSupport;

    @Resource
    private SecurityJwtAuthenticationFilter securityJwtAuthenticationFilter;

    @Resource
    private SecurityEntryPointHandler securityEntryPointHandler;

    @Resource
    private SecurityAccessSuccessHandler securityAccessSuccessHandler;

    @Resource
    private SecurityAccessFailureHandler securityAccessFailureHandler;

    @Resource
    private SecurityLogoutSuccessHandler securityLogoutSuccessHandler;

    /**
     * 自定义权限注解
     */
    @Bean
    public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(new SecurePermissionSupport());
        return handler;
    }

    /**
     * 自定义密码验证
     */
    @Bean
    public AuthenticationProvider rsaAuthenticationProvider() {
        AuthenticationProvider authenticationProvider = new AuthenticationProvider();
        authenticationProvider.setUserDetailsService(securityUserService);
        return authenticationProvider;
    }

    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                 // 禁止重写 configure(WebSecurity web) 方法，所有放行从这里填写
                .antMatchers("/", "/admin/**", "/guest/**", "/system/**",
                        "/template/**","/component/**","/favicon.ico", "/upload/**").permitAll()
                .anyRequest().authenticated();
        //http
                 // 验证码验证类
        //        .addFilterBefore(securityCaptchaSupport, UsernamePasswordAuthenticationFilter.class);
        http
                .formLogin().loginPage("/login.html").loginProcessingUrl("/login")
                .successHandler(securityAccessSuccessHandler)
                .failureHandler(securityAccessFailureHandler);
        http
                .exceptionHandling()
                .authenticationEntryPoint(securityEntryPointHandler);
        http
                .logout()
                .logoutSuccessHandler(securityLogoutSuccessHandler);
        http
                .sessionManagement()
                 //关闭session, v2版本基于token验证
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
                .rememberMe();
        http     // 关闭跨站请求伪造防护
                .csrf().disable();
        http     // 开启跨域
                .cors();
        http     // 关闭iframe防护
                .headers().frameOptions().disable();
        http
                .addFilterBefore(securityJwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
