javascript
Spring Security3源码分析-http标签解析(转)
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
在FilterChainProxy初始化的過程中,大概描述了標(biāo)簽解析的一些步驟,但不夠詳細(xì)
? <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標(biāo)簽的解析過程由類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相關(guān)類使用
??????? final String portMapperName = createPortMapper(element, pc);
??????? final UrlMatcher matcher = createUrlMatcher(element);
??????? //http標(biāo)簽構(gòu)造器,該構(gòu)造函數(shù)中對intercept-url、create-session子標(biāo)簽
???????? //進(jìn)行了預(yù)處理,并將所有的intercept-url信息放到List中。
??????? HttpConfigurationBuilder httpBldr = new HttpConfigurationBuilder(element, pc, matcher, portMapperName);
??????? //處理List中的intercept-url信息(如pattern、filters),并將結(jié)果放到
???????? //Map集合filterChainMap中
??????? httpBldr.parseInterceptUrlsForEmptyFilterChains();
??????? //創(chuàng)建過濾器SecurityContextPersistenceFilter
??????? httpBldr.createSecurityContextPersistenceFilter();
??????? //創(chuàng)建過濾器SessionManagementFilter
??????? httpBldr.createSessionManagementFilters();
??????? //新建一個(gè)空的provider集合
??????? ManagedList<BeanReference> authenticationProviders = new ManagedList<BeanReference>();
??????? //通過空的provider集合產(chǎn)生一個(gè)ProviderManager的bean定義
??????? BeanReference authenticationManager = createAuthenticationManager(element, pc, authenticationProviders, null);
??????? //創(chuàng)建過濾器SecurityContextHolderAwareRequestFilter
??????? httpBldr.createServletApiFilter();
??????? //判斷intercept-url標(biāo)簽是否有requires-channel屬性,如果有,則創(chuàng)建過濾器
???????? //ChannelProcessingFilter
??????? httpBldr.createChannelProcessingFilter();
??????? //創(chuàng)建過濾器FilterSecurityInterceptor
??????? //這個(gè)創(chuàng)建過程比較復(fù)雜,分別為:
???????? //1.需要判斷是否使用表達(dá)式use-expressions
??????? //2.解析intercept-url中的access等屬性
???????? //3.RoleVoter、AffirmativeBased的定義…………
??????? httpBldr.createFilterSecurityInterceptor(authenticationManager);
??????? //下面是與認(rèn)證有關(guān)的過濾器,HttpConfigurationBuilder,
???????? //AuthenticationConfigBuilder將解析的職責(zé)進(jìn)行了分離
??????? AuthenticationConfigBuilder authBldr = new AuthenticationConfigBuilder(element, pc,
??????????????? httpBldr.isAllowSessionCreation(), portMapperName);
??????? //創(chuàng)建過濾器AnonymousAuthenticationFilter,并且構(gòu)造了provider:
???????? //AnonymousAuthenticationProvider,供ProviderManager使用
??????? authBldr.createAnonymousFilter();
??????? //判斷是否有remember-me標(biāo)簽,如果有,則創(chuàng)建過濾器
???????? //RememberMeAuthenticationFilter,并且構(gòu)造了provider:
???????? //RememberMeAuthenticationProvider供ProviderManager使用
??????? authBldr.createRememberMeFilter(authenticationManager);
??????? //判斷是否有request-cache標(biāo)簽,如果有,則構(gòu)造ref指明的bean定義
???????? //如果沒有,則構(gòu)造HttpSessionRequestCache緩存
??????? authBldr.createRequestCache();
??????? //創(chuàng)建過濾器BasicAuthenticationFilter
??????? authBldr.createBasicFilter(authenticationManager);
??????? //創(chuàng)建LoginUrlAuthenticationEntryPoint,以及創(chuàng)建過濾器
???????? //UsernamePasswordAuthenticationFilter
??????? authBldr.createFormLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
??????? //判斷是否使用了openid-login,如果有,則構(gòu)造openId客戶端
???????? //org.springframework.security.openid.OpenID4JavaConsumer
??????? authBldr.createOpenIDLoginFilter(httpBldr.getSessionStrategy(), authenticationManager);
??????? //判斷是否使用了x509,如果有,則創(chuàng)建過濾器
???????? //X509AuthenticationFilter
??????? authBldr.createX509Filter(authenticationManager);
??????? //判斷是否配置了logout,如果有,則創(chuàng)建過濾器LogoutFilter
??????? authBldr.createLogoutFilter();
??????? //判斷是否配置login-page屬性,如果沒有,則創(chuàng)建過濾器
???????? //DefaultLoginPageGeneratingFilter,生成默認(rèn)登錄頁面
??????? authBldr.createLoginPageFilterIfNeeded();
??????? //創(chuàng)建UserDetailsServiceInjectionBeanPostProcessor
??????? //動態(tài)向x509、openID、rememberme服務(wù)注入U(xiǎn)serDetailsService
???????? //主要使用了spring的BeanPostProcessor接口功能
??????? authBldr.createUserServiceInjector();
??????? //創(chuàng)建過濾器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標(biāo)簽定義的Filter
??????? unorderedFilterChain.addAll(buildCustomFilterList(element, pc));
??????? //對FilterChian鏈中的Filter進(jìn)行排序,排序規(guī)則參見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);
??????? //構(gòu)造FilterChainProxy的Bean
??????? registerFilterChainProxy(pc, filterChainMap, matcher, source);
??????? pc.popAndRegisterContainingComponent();
??????? return null;
??? }
至此,大概http標(biāo)簽的解析已經(jīng)差不多了,雖然每個(gè)Filter的BeanDefinition創(chuàng)建過程還沒有一一細(xì)說,但基本步驟如下:
1.通過Filter的類路徑獲取BeanDefinitionBuilder對象,如
BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(filterClassName);
2.解析xml標(biāo)簽屬性,再通過BeanDefinitionBuilder的addPropertyValue、addPropertyReference等方法設(shè)置Filter對應(yīng)BeanDefinition的屬性值、依賴bean
3.注冊BeanDefinition。通過
ParserContext.registerBeanComponent(
new BeanComponentDefinition(BeanDefinition,beanId));
完成bean的注冊。還可以通過ParserContext.getRegistry().registerAlias
方法注冊bean的別名
實(shí)際上,標(biāo)簽解析就是構(gòu)造BeanDefinition,然后注冊到bean factory中。而BeanDefinition就是Spring中定義bean的數(shù)據(jù)結(jié)構(gòu)。
轉(zhuǎn)載于:https://my.oschina.net/blooms/blog/79106
總結(jié)
以上是生活随笔為你收集整理的Spring Security3源码分析-http标签解析(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ 3264 Balanced
- 下一篇: 开源GIS解决方案,暨GeoServer