`
Dead_knight
  • 浏览: 1193888 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
752c8642-b795-3fe6-946e-a4e845bffdec
Spring Securi...
浏览量:238238
33caa84e-18a6-3036-a82b-6e2106a4de63
clojure专题
浏览量:48068
E17ca077-44df-3816-a3fe-471c43f6e1e5
WebLogic11g
浏览量:235928
社区版块
存档分类
最新评论

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>

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的数据结构。
分享到:
评论
3 楼 xsd_旧 2015-11-08  
 
2 楼 Cappuccino12 2015-01-12  
有用~可是能不能 在解析下http标签里的属性都是什么意思?
1 楼 李永 2014-03-19  
 

相关推荐

    spring-security-oauth2源码

    spring security oauth2的源码,方便研究,备份一下。

    Spring_Security3_源码分析

    Spring_Security3_源码分析

    Android代码-logback

    Spring Security源码分析六:Spring Social 社交登录源码解析 Spring Security源码分析七:Spring Security 记住我 Spring Security源码分析八:Spring Security 退出 Spring Security源码分析九:Spring Security ...

    java开源包1

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    JAVA上百实例源码以及开源项目源代码

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

    java面试题及技巧4

    │ │ │ 275test-3.txt │ │ │ 275test-4.txt │ │ │ 275test.txt │ │ │ answer-1.txt │ │ │ answer-2.txt │ │ │ answer-3.txt │ │ │ answer-4.txt │ │ │ Desktop_.ini │ │ │ 考题_1.doc │ ...

    JAVA上百实例源码以及开源项目

     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...

    java面试题及技巧3

    │ │ │ 275test-3.txt │ │ │ 275test-4.txt │ │ │ 275test.txt │ │ │ answer-1.txt │ │ │ answer-2.txt │ │ │ answer-3.txt │ │ │ answer-4.txt │ │ │ Desktop_.ini │ │ │ 考题_1.doc │ ...

    java开源包8

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    java开源包3

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    java面试题以及技巧

    │ │ │ 275test-3.txt │ │ │ 275test-4.txt │ │ │ 275test.txt │ │ │ answer-1.txt │ │ │ answer-2.txt │ │ │ answer-3.txt │ │ │ answer-4.txt │ │ │ Desktop_.ini │ │ │ 考题_1.doc │ ...

    java面试题目与技巧1

    │ │ │ 275test-3.txt │ │ │ 275test-4.txt │ │ │ 275test.txt │ │ │ answer-1.txt │ │ │ answer-2.txt │ │ │ answer-3.txt │ │ │ answer-4.txt │ │ │ Desktop_.ini │ │ │ 考题_1.doc │ ...

    java面试题以及技巧6

    │ │ │ 275test-3.txt │ │ │ 275test-4.txt │ │ │ 275test.txt │ │ │ answer-1.txt │ │ │ answer-2.txt │ │ │ answer-3.txt │ │ │ answer-4.txt │ │ │ Desktop_.ini │ │ │ 考题_1.doc │ ...

    java开源包10

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    java开源包11

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    java开源包2

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    java开源包6

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    java开源包5

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

    java开源包4

    parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...

Global site tag (gtag.js) - Google Analytics