HttpSecurityBeanDefinitionParser浅析

HttpSecurityBeanDefinitionParser是众多SpringSecurity解析器中的一种,也是最为核心的一个解析器,其解析的节点是http声明的节点。

其主要作用有两个,

  • 实例化org.springframework.security.web.FilterChainProxy,并将其注入到Spring容器当中;
  • 根据配置文件初始化SpringSecurity的过滤器链,并将其注入到FilterChainProxy实例的filterChains属性中;

那么,这个类是如何将FilterChainProxy实例化并注入到Spring容器当中的呢?让我们直接贴代码

在我们解析xml文件的http节点时,首先进入这个类的parse方法

    public BeanDefinition parse(Element element, ParserContext pc) {
        CompositeComponentDefinition compositeDef =
            new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));
        pc.pushContainingComponent(compositeDef);
        //这个方法就是实例化FilterChainProxy对象,并注入进Spring容器
        registerFilterChainProxyIfNecessary(pc, pc.extractSource(element));

        // Obtain the filter chains and add the new chain to it
        //在原来过滤链集合的基础上添加新的过滤链
       BeanDefinition listFactoryBean = pc.getRegistry().getBeanDefinition(BeanIds.FILTER_CHAINS);
        List<BeanReference> filterChains = (List<BeanReference>)
                listFactoryBean.getPropertyValues().getPropertyValue("sourceList").getValue();
        //createFilterChain方法是得到过滤链
        filterChains.add(createFilterChain(element, pc));
pc.popAndRegisterContainingComponent(); return null; }


让我们来查看一下registerFilterChainProxyIfNecessary是如何做到的

    static void registerFilterChainProxyIfNecessary(ParserContext pc, Object source) {
        if (pc.getRegistry().containsBeanDefinition(BeanIds.FILTER_CHAIN_PROXY)) {
            return;
        }
        // Not already registered, so register the list of filter chains and the FilterChainProxy
        //创造一个ListFactoryBean,这个类的具体用法可以参考http://www.ithao123.cn/content-10108965.html
       BeanDefinition listFactoryBean = new RootBeanDefinition(ListFactoryBean.class);
        listFactoryBean.getPropertyValues().add("sourceList", new ManagedList());
        pc.registerBeanComponent(new BeanComponentDefinition(listFactoryBean, BeanIds.FILTER_CHAINS));
        //创造一个FilterChainProxy实例
        BeanDefinitionBuilder fcpBldr = BeanDefinitionBuilder.rootBeanDefinition(FilterChainProxy.class);
fcpBldr.getRawBeanDefinition().setSource(source);
//为定义添加构造方法参数,其指向的是一个listFactoryBean,实例化的时候会将listFactoryBean中的sourceList属性值付给对应的属性
      fcpBldr.addConstructorArgReference(BeanIds.FILTER_CHAINS);
fcpBldr.addPropertyValue("filterChainValidator", new RootBeanDefinition(DefaultFilterChainValidator.class)); BeanDefinition fcpBean = fcpBldr.getBeanDefinition();
//注入到Spring容器中,指定bean的id为org.springframework.security.filterChainProxy
pc.registerBeanComponent(new BeanComponentDefinition(fcpBean, BeanIds.FILTER_CHAIN_PROXY));
//设置此bean的别名为springSecurityFilterChain
 pc.getRegistry().registerAlias(BeanIds.FILTER_CHAIN_PROXY, BeanIds.SPRING_SECURITY_FILTER_CHAIN); }


让我们来查看一下createFilterChain方法是如何获取filterChains的

    private BeanReference createFilterChain(Element element, ParserContext pc) {
        //判断http节点的security属性是否为none值,如果是,则返回一个空的过滤器链,表示这个url不经过springsecurity的拦截
       boolean secured = !OPT_SECURITY_NONE.equals(element.getAttribute(ATT_SECURED));

        if (!secured) {
            //...........
            return createSecurityFilterChainBean(element, pc, Collections.emptyList());
        }

        final BeanReference portMapper = createPortMapper(element, pc);
        final BeanReference portResolver = createPortResolver(portMapper, pc);

        ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
        BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders);
        //对有关于http请求的节点属性进行解析
        HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc,
                portMapper, portResolver, authenticationManager);
        //对授权认证方面节点属性进行解析
        AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
                httpBldr.getSessionCreationPolicy(), httpBldr.getRequestCache(), authenticationManager,
                httpBldr.getSessionStrategy(), portMapper, portResolver);
        //设置登出成功的处理器
        httpBldr.setLogoutHandlers(authBldr.getLogoutHandlers());

        authenticationProviders.addAll(authBldr.getProviders());

        List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
        //添加关于http的一些拦截器
        unorderedFilterChain.addAll(httpBldr.getFilters());
        //添加授权认证的一些拦截器 
       unorderedFilterChain.addAll(authBldr.getFilters());
        //添加自定义拦截器
       unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
        //对这些拦截器进行排序
        Collections.sort(unorderedFilterChain, new OrderComparator());
        checkFilterChainOrder(unorderedFilterChain, pc, pc.extractSource(element));

        // The list of filter beans
        List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();

        for (OrderDecorator od : unorderedFilterChain) {
            filterChain.add(od.bean);
        }
        //返回封装后的过滤器链
        return createSecurityFilterChainBean(element, pc, filterChain);
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值