shiro与springboot整合原理

首先在我们之前的chapter1文章中讲到shiro配置类中有这个方法:

   @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/static/**", "anon");
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout.html", "logout");
        //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
        filterChainDefinitionMap.put("/**", "authc");
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/index.html");

        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

就从这个方法开始讲shiro与springboot是如何整合在一起的。首先该方法中实例化了一个ShiroFilterFactoryBean,继承结构为:

可以明显看出,该类实现了Spring中的FactoryBean和BeanPostProcessor接口,来看看都做了那些事情

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //如果该bean实现了java.servlet.Filter接口,则把该bean添加到该类的内部变量
        //Map<String,Filter> filters;中,以后再传到过滤器链中
        if (bean instanceof Filter) {
          
            Filter filter = (Filter) bean;
         //如何该过滤器继承了AccessControlFilter,AuthenticationFilter,AuthorizationFilter
//而且没有更改默认的登录url,登录成功url,权限失败url,就设置成上面我们在配置类中传入的url,否则不用我们上面设置的url
            applyGlobalPropertiesIfNecessary(filter);
            getFilters().put(beanName, filter);
        } else {
           
        }
        return bean;
    }

    //没做啥事,直接返回
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

然后再看BeanFactory接口中的方法实现,此方法的主要目的是生成shiro的一个过滤器,拦截每一个request请求,该过滤器中又包含所有(shiro内部拦截器和我们自己添加进去的拦截器)拦截器。

 public Object getObject() throws Exception {
        if (instance == null) {
            instance = createInstance();
        }
        return instance;
    }

此方法主要验证securityManager实例的有效性,就是我们上面注入到ShiroFilterBeanFactory中的那个。然后,哈哈,这里会创建一个默认的过滤器链管理类,shiro内部自己实现的,这就涉及到了过滤器设计模式了。关于shiro这里的过滤器设计代码就不在这里分析了,会单独写篇文章分析。最后把securityManager和chainResolver传入SpringShiroFilter

  protected AbstractShiroFilter createInstance() throws Exception {

      
        SecurityManager securityManager = getSecurityManager();
        if (securityManager == null) {
         
            throw new BeanInitializationException(msg);
        }

        if (!(securityManager instanceof WebSecurityManager)) {
         
            throw new BeanInitializationException(msg);
        }

        FilterChainManager manager = createFilterChainManager();
        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
        chainResolver.setFilterChainManager(manager);    
        return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
    }

 

protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
            super();
            if (webSecurityManager == null) {
                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
            }
            setSecurityManager(webSecurityManager);
            if (resolver != null) {
                setFilterChainResolver(resolver);
            }
        }

在哪里把SecurityManager保存在 ThreadContext 中的那 ?原来是执行Filter 的init方法的时候:

public final void init(FilterConfig filterConfig) throws ServletException {
        setFilterConfig(filterConfig);
        try {
            onFilterConfigSet();
        } catch (Exception e) {
            if (e instanceof ServletException) {
                throw (ServletException) e;
            } else {
                if (log.isErrorEnabled()) {
                    log.error("Unable to start Filter: [" + e.getMessage() + "].", e);
                }
                throw new ServletException(e);
            }
        }
    }
 protected final void onFilterConfigSet() throws Exception {
        //added in 1.2 for SHIRO-287:
        applyStaticSecurityManagerEnabledConfig();
        init();
        ensureSecurityManager();
        //added in 1.2 for SHIRO-287:
        if (isStaticSecurityManagerEnabled()) {
            SecurityUtils.setSecurityManager(getSecurityManager());
        }
    }

SecurityUtils.setSecurityManager(getSecurityManager());真想大白了,所以我们能过该工具类获取到SecurityManager

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值