Shiro核心配置类解析

@Configuration
@Import({ShiroBeanConfiguration.class,
        ShiroAnnotationProcessorConfiguration.class,
        ShiroWebConfiguration.class,
        ShiroWebFilterConfiguration.class,
        ShiroRequestMappingConfig.class})
public class ShiroConfig {

    // 非注解版本
    // @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();

        // 以“admin”角色登录的用户
        chainDefinition.addPathDefinition("/login/**", "anon");
        chainDefinition.addPathDefinition("/admin/**", "authc, roles[ROLE_ADMIN]");

        // 具有“document:read”权限的登录用户
        chainDefinition.addPathDefinition("/docs/**", "authc, perms[sys:user:select]");

        // 所有其他路径都需要登录用户
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }

}

// 处理Shiro相关Bean的类,因为Shiro提供了EventBus机制,还有提供了初始化和销毁的类,用于整合Spring
class ShiroBeanConfiguration {

    // 处理Shiro的Bean初始化和销毁的后置处理器
    // 主要用来处理Destroyable,Initializable
    // 1. ((Destroyable) obj).destroy();
    // 2. ((Initializable) obj).init();
    @Bean
    @Override
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    // 事件分发器
    @Bean
    @Override
    protected EventBus eventBus() {
        return new DefaultEventBus();
    }

    // Bean的后置处理器,找Bean中是否存在shiro的@Subscribe的Bean,负责发送一步事件
    @Bean
    @Override
    public ShiroEventBusBeanPostProcessor shiroEventBusAwareBeanPostProcessor() {
        return new ShiroEventBusBeanPostProcessor(eventBus());
    }
}

// 处理授权认证注解的后置处理器
class ShiroAnnotationProcessorConfiguration {
    // 导入一个创建AOP代理对象的后置处理器
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        return new DefaultAdvisorAutoProxyCreator();
    }

    // 导入一个人切面,为存在  new Class[] { RequiresPermissions.class, RequiresRoles.class,RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class};
    // 这些注解的类生成代理对象,并且进行拦截
    @Bean
    protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

// Shiro的核心注解注册到SpringWeb中的配置,都是默认配置
class ShiroWebConfiguration {

    // 保存Subject的DAO
    @Bean
    @Override
    protected SubjectDAO subjectDAO() {
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
        return subjectDAO;
    }

    // 控制哪些Session需要进行持久化
    @Bean
    @Override
    protected SessionStorageEvaluator sessionStorageEvaluator() {
        return new DefaultWebSessionStorageEvaluator();
    }

    // 创建Session的工厂
    @Bean
    @Override
    protected SessionFactory sessionFactory() {
        return new SimpleSessionFactory();
    }

    // 保存Session的DAO,默认保存在内存中
    @Bean
    @Override
    protected SessionDAO sessionDAO() {
        return new MemorySessionDAO();
    }

    // Shiro中存储Session(JSSessionId)Cookie的模板,Shiro会按照这个模板存储Session的相关信息
    @Bean(name = "sessionCookieTemplate")
    @Override
    protected Cookie sessionCookieTemplate() {
        return buildCookie(
                sessionIdCookieName,
                sessionIdCookieMaxAge,
                sessionIdCookiePath,
                sessionIdCookieDomain,
                sessionIdCookieSecure,
                sessionIdCookieSameSite);
    }

    // Shiro中处理Remember-Me的Cookie的模板,Shiro会按照这个模板存储Session的相关信息
    @Bean(name = "rememberMeCookieTemplate")
    @Override
    protected Cookie rememberMeCookieTemplate() {
        return buildCookie(
                rememberMeCookieName,
                rememberMeCookieMaxAge,
                rememberMeCookiePath,
                rememberMeCookieDomain,
                rememberMeCookieSecure,
                rememberMeSameSite);
    }

    protected Cookie buildCookie(String name, int maxAge, String path, String domain, boolean secure, Cookie.SameSiteOptions sameSiteOption) {
        Cookie cookie = new SimpleCookie(name);
        cookie.setHttpOnly(true);
        cookie.setMaxAge(maxAge);
        cookie.setPath(path);
        cookie.setDomain(domain);
        cookie.setSecure(secure);
        cookie.setSameSite(sameSiteOption);
        return cookie;
    }

    // 处理RememberMe的管理器
    @Bean
    @Override
    protected RememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookieTemplate());
        return cookieRememberMeManager;
    }

    // 创建Subject的工厂
    @Bean
    @Override
    protected SubjectFactory subjectFactory() {
        return new DefaultSubjectFactory();
    }

    // 创建授权管理器
    @Bean
    @Override
    protected Authorizer authorizer() {
        ModularRealmAuthorizer authorizer = new ModularRealmAuthorizer();
        if (permissionResolver != null) {
            authorizer.setPermissionResolver(permissionResolver);
        }
        if (rolePermissionResolver != null) {
            authorizer.setRolePermissionResolver(rolePermissionResolver);
        }
        return authorizer;
    }

    // 默认的认证策略,至少一个Realm处理成功
    @Bean
    @Override
    protected AuthenticationStrategy authenticationStrategy() {
        return new AtLeastOneSuccessfulStrategy();
    }

    // 认证管理器
    @Bean
    @Override
    protected Authenticator authenticator() {
        ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
        authenticator.setAuthenticationStrategy(authenticationStrategy());
        return authenticator;
    }

    // Session会话管理器
    @Bean
    @Override
    protected SessionManager sessionManager() {
        if (useNativeSessionManager) {
            return nativeSessionManager();
        }
        return new ServletContainerSessionManager();
    }

    // 本地Session管理,默认使用Servlet的HttpSession,持久化机制不太好用,如果使用Shiro内置的Session就比较方便
    protected SessionManager nativeSessionManager() {
        DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
        webSessionManager.setSessionIdCookieEnabled(sessionIdCookieEnabled);
        webSessionManager.setSessionIdUrlRewritingEnabled(sessionIdUrlRewritingEnabled);
        webSessionManager.setSessionIdCookie(sessionCookieTemplate());

        webSessionManager.setSessionFactory(sessionFactory());
        webSessionManager.setSessionDAO(sessionDAO());
        webSessionManager.setDeleteInvalidSessions(sessionManagerDeleteInvalidSessions);

        return webSessionManager;
    }

    // Shiro的核心主键,安全管理器
    @Bean
    @Override
    protected SessionsSecurityManager securityManager(List<Realm> realms) {
        SessionsSecurityManager securityManager = createSecurityManager();
        securityManager.setAuthenticator(authenticator());
        securityManager.setAuthorizer(authorizer());
        securityManager.setRealms(realms);
        securityManager.setSessionManager(sessionManager());
        securityManager.setEventBus(eventBus);
        if (cacheManager != null) {
            securityManager.setCacheManager(cacheManager);
        }
        return securityManager;
    }

    @Override
    protected SessionsSecurityManager createSecurityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setSubjectDAO(subjectDAO());
        securityManager.setSubjectFactory(subjectFactory());
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    // 默认的过滤器链定义信息,创建的过滤器会引用该Bean的配置,来定义过滤器的需要拦截的路径
    @Bean
    @Override
    protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/**", "authc");
        return chainDefinition;
    }

    // Shiro整合SpringMVC需要使用到的路径解析工具类,因为Shiro有自己的路径规则
    @Bean
    @Override
    protected ShiroUrlPathHelper shiroUrlPathHelper() {
        return new ShiroUrlPathHelper();
    }
}

// 注册Shiro整合SpringMVC的过滤器
@Configuration
public class ShiroWebFilterConfiguration {

    // 使用FactoryBean机制注册,内部注册核心过滤器SpringShiroFilter
    @Bean
    @Override
    protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
        // 默认生成SpringShiroFilter类型的过滤器
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        // 设置登录相关的属性配置
        filterFactoryBean.setLoginUrl(loginUrl);
        filterFactoryBean.setSuccessUrl(successUrl);
        filterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
        filterFactoryBean.setSecurityManager(securityManager);
        filterFactoryBean.setShiroFilterConfiguration(shiroFilterConfiguration());
        // 全局的过滤器,默认有一个为invalidRequest
        filterFactoryBean.setGlobalFilters(globalFilters());
        // 获取自定义的拦截过滤器链定义信息,这些定义的字符串最终会解析成过滤器会整到拦截器链中
        // 因此我们一般只需要定义它就能完成拦截配置,而不需要定义指定ShiroFilter
        filterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition.getFilterChainMap());
        // 自定义的过滤器的Bean
        if (filterMap != null) {
            filterFactoryBean.setFilters(filterMap);
        }
        return filterFactoryBean;
    }

    // 全局配置
    @Bean(name = "globalFilters")
    protected List<String> globalFilters() {
        // 默认存在全局的过滤器为invalidRequest
        return Collections.singletonList(DefaultFilter.invalidRequest.name());
    }
}

// 重写SpringMVC中RequestMappingHandlerMapping的URL解析器
@Configuration
public class ShiroRequestMappingConfig {
    // 重写SpringMVC中RequestMappingHandlerMapping的URL解析器
    public ShiroRequestMappingConfig(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        requestMappingHandlerMapping.setUrlPathHelper(new ShiroUrlPathHelper());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值