package cn.palmte.work.shiro;

import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
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.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.mgt.SecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by wang.lin@esstx.cn on 2018/4/17.
 */
@Configuration
public class ShiroConfig {
    private static final Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.class);

    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("shiroAuthorizingRealm") ShiroAuthorizingRealm shiroAuthorizingRealm,
                                           @Qualifier("cookieRememberMeManager") CookieRememberMeManager cookieRememberMeManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(shiroAuthorizingRealm);

        // 设置rememberMe管理器
        securityManager.setRememberMeManager(cookieRememberMeManager);
        // 设置缓存管理器
        securityManager.setCacheManager(new MemoryConstrainedCacheManager());
        return securityManager;
    }

    /**
     * realm
     */
    @Bean(name = "shiroAuthorizingRealm")
    public ShiroAuthorizingRealm shiroAuthorizingRealm(
            @Qualifier("simpleCredentialsMatcher") SimpleCredentialsMatcher matcher
    ) {
//        @Qualifier("ehCacheManager") EhCacheManager  ehCacheManager
        log.info("myShiroRealm()");
        ShiroAuthorizingRealm myAuthorizingRealm = new ShiroAuthorizingRealm();
        // 设置密码凭证匹配器
        myAuthorizingRealm.setCredentialsMatcher(matcher); // myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());

        return myAuthorizingRealm;
    }


    /**
     * cookie对象;
     */
    @Bean
    public SimpleCookie rememberMeCookie() {
        log.info("rememberMeCookie()");
        // 这个参数是cookie的名称，对应前端的checkbox 的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        // <!-- 记住我cookie生效时间30天（259200） ,单位秒;-->
        simpleCookie.setMaxAge(259200);
        return simpleCookie;
    }

    /**
     * 记住我管理器 cookie管理对象;
     */
    @Bean(name = "cookieRememberMeManager")
    public CookieRememberMeManager rememberMeManager() {
        System.out.println("rememberMeManager()");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }

    /**
     * 密码匹配凭证管理器
     */
    @Bean(name = "simpleCredentialsMatcher")
    public SimpleCredentialsMatcher simpleCredentialsMatcher() {
        SimpleCredentialsMatcher simpleCredentialsMatcher = new SimpleCredentialsMatcher();
        return simpleCredentialsMatcher;
    }

    /**
     * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持; Controller才能使用@RequiresPermissions
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            @Qualifier("securityManager") SecurityManager securityManager) {
        log.info("authorizationAttributeSourceAdvisor()");
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * shiro管理生命周期的东西
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 拦截器.
        Map<String, String> map = new LinkedHashMap<String, String>();

        //特殊URL放开
        map.put("/admin/login", "anon");
        map.put("/admin/logout", "logout");
        map.put("/admin/singIn", "anon");
        map.put("/admin/err", "anon");
        map.put("/admin/captcha", "anon");
        map.put("/api/**", "anon");
        map.put("/file/**", "anon");


        //静态资源放开, 以后所有的静态资源都放到这些目录下,否则需要在此添加映射
        map.put("/assets/**", "anon");
        map.put("/common/**", "anon");
        map.put("/favicon.png", "anon");
        map.put("/img/**", "anon");
        map.put("/jqPaginator/**", "anon");
        map.put("/layer/**", "anon");
        map.put("/ueditor/**", "anon");


//        map.put("/admin/login", "authc");
//        map.put("/admin/center", "authc");
//        map.put("/admin/console", "authc");
//        map.put("/account/password", "authc");
//        map.put("/account/updatePassword", "authc");
        map.put("/**", "authc");

        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/admin/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/admin/center");
        // 未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//        Map<String,Filter> filterMap = new LinkedHashMap<>();
//        filterMap.put("perms",new ShiroPermissionsFilter());
//        shiroFilterFactoryBean.setFilters(filterMap);
        return shiroFilterFactoryBean;
    }

}
