Spring Security3源碼分析-http標籤解析(轉)

在FilterChainProxy初始化的過程當中,大概描述了標籤解析的一些步驟,但不夠詳細
  <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>web

http標籤的解析過程由類org.springframework.security.config.http.HttpSecurityBeanDefinitionParser解析。
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
        //動態向x50九、openID、rememberme服務注入UserDetailsService
         //主要使用了spring的BeanPostProcessor接口功能
        authBldr.createUserServiceInjector();
        //建立過濾器ExceptionTranslationFilter
        authBldr.createExceptionTranslationFilter();spring

        List<OrderDecorator> unorderedFilterChain = new ArrayList<OrderDecorator>();
        //向FilterChain鏈中添加filters
        unorderedFilterChain.addAll(httpBldr.getFilters());
        unorderedFilterChain.addAll(authBldr.getFilters());
        //向ProviderManager中添加provider
        authenticationProviders.addAll(authBldr.getProviders());express

        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>();session

        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);app

        pc.popAndRegisterContainingComponent();
        return null;
    }jsp

至此,大概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的數據結構。 ide

相關文章
相關標籤/搜索