您的位置:首页 > 理论基础 > 计算机网络

Spring Security3源码分析(2)-http标签解析

2014-09-11 11:49 411 查看
在FilterChainProxy初始化的过程中,大概描述了标签解析的一些步骤,但不够详细 

Xml代码  


<http auto-config="true">  

  <remember-me key="workweb" token-validity-seconds="3600" data-source-ref="dataSource"/>  

  <form-login login-page="/login.jsp"/>  

  <logout logout-success-url="/login.jsp"/>  

  <intercept-url pattern="/*" access="ROLE_USER"/>  

</http>  

http标签的解析过程由类org.springframework.security.config.http.HttpSecurityBeanDefinitionParser解析。 

Java代码  


public BeanDefinition parse(Element element, ParserContext pc) {  

        CompositeComponentDefinition compositeDef =  

            new CompositeComponentDefinition(element.getTagName(), pc.extractSource(element));  

        pc.pushContainingComponent(compositeDef);  

        final Object source = pc.extractSource(element);  

        //portMapperName、matcher主要提供给SSL相关类使用  

        final String portMapperName = createPortMapper(element, pc);  

        final UrlMatcher matcher = createUrlMatcher(element);  

        //http标签构造器,该构造函数中对intercept-url、create-session子标签  

         //进行了预处理,并将所有的intercept-url信息放到List中。  

        HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc, matcher, portMapperName);  

        //处理List中的intercept-url信息(如pattern、filters),并将结果放到  

         //Map集合filterChainMap中  

        httpBldr.parseInterceptUrlsForEmptyFilterChains();  

        //创建过滤器SecurityContextPersistenceFilter  

        httpBldr.createSecurityContextPersistenceFilter();  

        //创建过滤器SessionManagementFilter  

        httpBldr.createSessionManagementFilters();  

        //新建一个空的provider集合  

        ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();  

        //通过空的provider集合产生一个ProviderManager的bean定义  

        BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders, null);  

        //创建过滤器SecurityContextHolderAwareRequestFilter  

        httpBldr.createServletApiFilter();  

        //判断intercept-url标签是否有requires-channel属性,如果有,则创建过滤器  

         //ChannelProcessingFilter  

        httpBldr.createChannelProcessingFilter();  

        //创建过滤器FilterSecurityInterceptor  

        //这个创建过程比较复杂,分别为:  

         //1.需要判断是否使用表达式use-expressions  

        //2.解析intercept-url中的access等属性  

         //3.RoleVoter、AffirmativeBased的定义…………  

        httpBldr.createFilterSecurityInterceptor(authenticationManager);  

        //下面是与认证有关的过滤器,HttpConfigurationBuilder,  

         //AuthenticationConfigBuilder将解析的职责进行了分离  

        AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,  

                httpBldr.isAllowSessionCreation(), portMapperName);  

        //创建过滤器AnonymousAuthenticationFilter,并且构造了provider:  

         //AnonymousAuthenticationProvider,供ProviderManager使用  

        authBldr.createAnonymousFilter();  

        //判断是否有remember-me标签,如果有,则创建过滤器  

         //RememberMeAuthenticationFilter,并且构造了provider:  

         //RememberMeAuthenticationProvider供ProviderManager使用  

        authBldr.createRememberMeFilter(authenticationManager);  

        //判断是否有request-cache标签,如果有,则构造ref指明的bean定义  

         //如果没有,则构造HttpSessionRequestCache缓存  

        authBldr.createRequestCache();  

        //创建过滤器BasicAuthenticationFilter  

        authBldr.createBasicFilter(authenticationManager);  

        //创建LoginUrlAuthenticationEntryPoint,以及创建过滤器  

         //UsernamePasswordAuthenticationFilter  

        authBldr.createFormLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);  

        //判断是否使用了openid-login,如果有,则构造openId客户端  

         //org.springframework.security.openid.OpenID4JavaConsumer  

        authBldr.createOpenIDLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);  

        //判断是否使用了x509,如果有,则创建过滤器  

         //X509AuthenticationFilter  

        authBldr.createX509Filter(authenticationManager);  

        //判断是否配置了logout,如果有,则创建过滤器LogoutFilter  

        authBldr.createLogoutFilter();  

        //判断是否配置login-page属性,如果没有,则创建过滤器  

         //DefaultLoginPageGeneratingFilter,生成默认登录页面  

        authBldr.createLoginPageFilterIfNeeded();  

        //创建UserDetailsServiceInjectionBeanPostProcessor  

        //动态向x509、openID、rememberme服务注入UserDetailsService  

         //主要使用了spring的BeanPostProcessor接口功能  

        authBldr.createUserServiceInjector();  

        //创建过滤器ExceptionTranslationFilter  

        authBldr.createExceptionTranslationFilter();  

  

        List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();  

        //向FilterChain链中添加filters  

        unorderedFilterChain.addAll(httpBldr.getFilters());  

        unorderedFilterChain.addAll(authBldr.getFilters());  

        //向ProviderManager中添加provider  

        authenticationProviders.addAll(authBldr.getProviders());  

  

        BeanDefinition requestCacheAwareFilter = new RootBeanDefinition(RequestCacheAwareFilter.class);  

        requestCacheAwareFilter.getPropertyValues().addPropertyValue("requestCache", authBldr.getRequestCache());  

        unorderedFilterChain.add(new OrderDecorator(requestCacheAwareFilter, REQUEST_CACHE_FILTER));  

        //添加自定义的Filter,也就是custom-filter标签定义的Filter  

        unorderedFilterChain.addAll(buildCustomFilterList(element, pc));  

        //对FilterChian链中的Filter进行排序,排序规则参见SecurityFilters枚举类  

        Collections.sort(unorderedFilterChain, new OrderComparator());  

        checkFilterChainOrder(unorderedFilterChain, pc, source);  

  

        List<BeanMetadataElement> filterChain = new ManagedList<BeanMetadataElement>();  

  

        for (OrderDecorator od : unorderedFilterChain) {  

            filterChain.add(od.bean);  

        }  

  

        ManagedMap<BeanDefinition, List<BeanMetadataElement>> filterChainMap = httpBldr.getFilterChainMap();  

        BeanDefinition universalMatch = new RootBeanDefinition(String.class);  

        universalMatch.getConstructorArgumentValues().addGenericArgumentValue(matcher.getUniversalMatchPattern());  

        filterChainMap.put(universalMatch, filterChain);  

        //构造FilterChainProxy的Bean  

        registerFilterChainProxy(pc, filterChainMap, matcher, source);  

  

        pc.popAndRegisterContainingComponent();  

        return null;  

    }  

至此,大概http标签的解析已经差不多了,虽然每个Filter的BeanDefinition创建过程还没有一一细说,但基本步骤如下: 

1.通过Filter的类路径获取BeanDefinitionBuilder对象,如 

BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName); 

2.解析xml标签属性,再通过BeanDefinitionBuilder的addPropertyValue、addPropertyReference等方法设置Filter对应BeanDefinition的属性值、依赖bean 

3.注册BeanDefinition。通过 

ParserContext.registerBeanComponent( 

new BeanComponentDefinition(BeanDefinition,beanId)); 

完成bean的注册。还可以通过ParserContext.getRegistry().registerAlias 

方法注册bean的别名 

实际上,标签解析就是构造BeanDefinition,然后注册到bean factory中。而BeanDefinition就是Spring中定义bean的数据结构。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息