javascript
Spring Security3源码分析-http标签解析(转)
為什么80%的碼農都做不了架構師?>>> ??
在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>
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
??????? //動態向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的數據結構。
轉載于:https://my.oschina.net/blooms/blog/79106
總結
以上是生活随笔為你收集整理的Spring Security3源码分析-http标签解析(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ 3264 Balanced
- 下一篇: 加载gif图片html,JS实现的自定义