package com.bofeng.security;

import com.bofeng.Consts;
import com.bofeng.service.SecurityService;
import com.google.common.collect.Maps;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import javax.servlet.Filter;
import java.util.Map;

/**
 * Created by luoyifan on 2018/8/23.
 */
@Configuration
public class ShiroAutoConfiguration {

    @Autowired
    @Lazy
    private SecurityService securityService;

    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator v = new DefaultAdvisorAutoProxyCreator();
        v.setProxyTargetClass(true);
        return v;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public SecurityManager securityManager(HybJwtRealm hybJwtRealm) {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(hybJwtRealm);

        DefaultSessionStorageEvaluator storageEvaluator = new DefaultSessionStorageEvaluator();
        storageEvaluator.setSessionStorageEnabled(false);


        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        subjectDAO.setSessionStorageEvaluator(storageEvaluator);

        manager.setSubjectDAO(subjectDAO);
        return manager;
    }


    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题。
     * 注意：单独一个ShiroFilterFactoryBean配置是或报错的，因为在
     * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
     * <p>
     * Filter Chain定义说明
     * 1、一个URL可以配置多个Filter，使用逗号分隔
     * 2、当设置多个过滤器时，全部验证通过，才视为通过
     * 3、部分过滤器可指定参数，如 perms，roles
     */
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        Map<String, Filter> filterMap = Maps.newLinkedHashMap();
        filterMap.put("jwt", new JwtFilter(securityService));
        shiroFilterFactoryBean.setFilters(filterMap);

        Map<String, String> filterRuleMap = Maps.newLinkedHashMap();
        filterRuleMap.put("/admin/**", "jwt");
        filterRuleMap.put("/cashier/**", "jwt");
        filterRuleMap.put("/worker/**", "jwt");
        for (String path : Consts.NOT_SECURITY_PATHS) {
            filterRuleMap.put(path, "anon");
        }
        //filterRuleMap.put("/static/**", "anon");
        //filterRuleMap.put("/user/**", "anon");
        //filterRuleMap.put("/error/**", "anon");
        //filterRuleMap.put("/v2/**", "anon");
        //filterRuleMap.put("/swagger-resources/**", "anon");
        //filterRuleMap.put("/favicon.ico","anon");

        //shiroFilterFactoryBean.setLoginUrl("/user/login.html");
        //shiroFilterFactoryBean.setUnauthorizedUrl("/error/401");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return shiroFilterFactoryBean;
    }

}
