/**
 * Copyright (c) 2022 cloud Authors. All Rights Reserved.
 *
 * 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 com.lutao.cloud.auth.config;

import com.lutao.cloud.auth.sso.config.SSOSecurityConfigurer;
import com.lutao.cloud.auth.sso.handler.SSOLoginSuccessHandler;
import com.lutao.cloud.common.security.handler.FormAuthenticationFailureHandler;
import com.lutao.cloud.common.security.handler.MobileLoginSuccessHandler;
import com.lutao.cloud.common.security.handler.SsoLogoutSuccessHandler;
import com.lutao.cloud.common.security.handler.TenantSavedRequestAwareAuthenticationSuccessHandler;
import com.lutao.cloud.common.security.mobile.MobileSecurityConfigurer;
import com.lutao.cloud.common.security.password.PasswordEncoderSha;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
 * @date 2018/6/22 认证相关配置
 */
@Primary
@Order(90)
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter{

    /**
     * 表单登录配置安全策略
     * @param http
     */
    @Override
    @SneakyThrows
    protected void configure(HttpSecurity http) {
        http.formLogin().loginPage("/token/login").loginProcessingUrl("/token/form")
            .successHandler(tenantSavedRequestAwareAuthenticationSuccessHandler())
            .failureHandler(authenticationFailureHandler()).and().logout()
            .logoutSuccessHandler(logoutSuccessHandler()).deleteCookies("JSESSIONID").invalidateHttpSession(true)
            .and().authorizeRequests().antMatchers("/token/**", "/actuator/**", "/mobile/**").permitAll()
            .anyRequest().authenticated().and().csrf().disable().apply(mobileSecurityConfigurer()).and().apply(ssoSecurityConfigurer());
    }

    /**
     * 不拦截静态资源
     *
     * @param web
     */
    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/favicon.ico", "/css/**", "/error");
    }

    /**
     * 密码模式
     * @return
     */
    @Bean
    @Override
    @SneakyThrows
    public AuthenticationManager authenticationManagerBean(){
        return super.authenticationManagerBean();
    }

    /**
     * 授权处理
     * @return
     */
    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler(){
        return new FormAuthenticationFailureHandler();
    }

    /**
     * 登出成功处理
     * @return
     */
    @Bean
    public LogoutSuccessHandler logoutSuccessHandler(){
        return new SsoLogoutSuccessHandler();
    }

    /**
     * 移动登录成功处理
     * @return
     */
    @Bean
    public AuthenticationSuccessHandler mobileLoginSuccessHandler(){
        return new MobileLoginSuccessHandler();
    }

    /**
     * 具备租户传递能力
     *
     * @return AuthenticationSuccessHandler
     */
    @Bean
    public AuthenticationSuccessHandler tenantSavedRequestAwareAuthenticationSuccessHandler(){
        return new TenantSavedRequestAwareAuthenticationSuccessHandler();
    }

    /**
     * 移动加密配置
     * @return
     */
    @Bean
    public MobileSecurityConfigurer mobileSecurityConfigurer(){
        return new MobileSecurityConfigurer();
    }

    @Bean
    public SSOSecurityConfigurer ssoSecurityConfigurer(){
        return new SSOSecurityConfigurer();
    }

    @Bean
    public SSOLoginSuccessHandler ssoLoginSuccessHandler(){
        return new SSOLoginSuccessHandler();
    }

    /**
     * https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-updated
     * Encoded password does not look like BCrypt
     *
     * @return PasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return PasswordEncoderSha.getInstance();
//        return new BCryptPasswordEncoder();
    }

}
