{"action":"opened","issue":{"url":"https://api.github.com/repos/spring-projects/spring-security/issues/4141","repository_url":"https://api.github.com/repos/spring-projects/spring-security","labels_url":"https://api.github.com/repos/spring-projects/spring-security/issues/4141/labels{/name}","comments_url":"https://api.github.com/repos/spring-projects/spring-security/issues/4141/comments","events_url":"https://api.github.com/repos/spring-projects/spring-security/issues/4141/events","html_url":"https://github.com/spring-projects/spring-security/issues/4141","id":191651882,"number":4141,"title":"Unpredictable context files loading order causes <sec:http element to crash context startup","user":{"login":"djechelon","id":3042285,"avatar_url":"https://avatars.githubusercontent.com/u/3042285?v=3","gravatar_id":"","url":"https://api.github.com/users/djechelon","html_url":"https://github.com/djechelon","followers_url":"https://api.github.com/users/djechelon/followers","following_url":"https://api.github.com/users/djechelon/following{/other_user}","gists_url":"https://api.github.com/users/djechelon/gists{/gist_id}","starred_url":"https://api.github.com/users/djechelon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/djechelon/subscriptions","organizations_url":"https://api.github.com/users/djechelon/orgs","repos_url":"https://api.github.com/users/djechelon/repos","events_url":"https://api.github.com/users/djechelon/events{/privacy}","received_events_url":"https://api.github.com/users/djechelon/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-11-25T08:53:04Z","updated_at":"2016-11-25T08:53:04Z","closed_at":null,"body":"### Summary\r\n\r\nWe maintain a modular application that consists (from the Spring configuration perspective) of multiple context files (xml) supplied by different modules, inside each module's jar.\r\nWe also have a global `platform-security-context.xml` file that contains the basic settings for application security context, e.g. the standard authentication handler, a few paths that have to be protected/unprotected, etc. Example is given in the configuration section\r\n\r\nWe also employ a naming convention `[module-name]-{data|web|security|integration|test}-context.xml\" for module-related context files, and they are all deployed to each jar's `META-INF/context/` so Spring can load all the contexts via web.xml using `classpath*:META-INF/context/*-context.xml` syntax.\r\n\r\nThe problem occurs when a module wants to define its custom paths (e.g. configure custom authentication under `/rest/....`). In the near future, we are going to require new modules to add their XML security configuration to the entire platform as our application are going to communicate more with external systems.\r\n\r\nSpring Security requires that the _patternless_ `<http>` element, which is the default, occurs as last in the sequence. With multiple context files, if different context files specify `<http>` elements, all depends on the order the files are loaded.\r\n\r\nBasing on our experience, and this is the reason why we are opening a ticket, the order the context files are loaded is not always deterministic on different application servers/OSes. In most cases, alphabetically ordering context files grants them to be loaded in their natural order, but there have been random-unpredictable cases in which the deployed application didn't follow the file name order. And even if it was 100% alphabetically-deterministic, I think that it is quite ugly having to consider the loading order of the files when dealing with Spring context files, all elements under the same `<beans>` element should be treated equal :-)\r\n\r\nThe request is to review the mechanism Spring Security uses to load XML definition of security elements and if possible to pre-order them putting the _patternless_ `<http>` element at the end of the list.\r\n\r\n### Actual Behavior\r\n\r\nWhen the context starts, I get the following error\r\n\r\n```\r\norg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.filterChainProxy': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: A universal match pattern ('/**') is defined  before other patterns in the filter chain, causing them to be ignored. Please check the ordering in your <security:http> namespace or FilterChainProxy bean configuration\r\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583)\r\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)\r\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)\r\n\tat org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)\r\n\tat org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)\r\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)\r\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)\r\n\tat org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751)\r\n\tat org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)\r\n\tat org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:541)\r\n\tat org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java)\r\n\tat org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)\r\n\tat org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)\r\n\tat org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)\r\n\tat org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5099)\r\n\tat org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5615)\r\n\tat org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)\r\n\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1571)\r\n\tat org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1561)\r\n\tat java.util.concurrent.FutureTask.run(FutureTask.java:262)\r\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)\r\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)\r\n\tat java.lang.Thread.run(Thread.java:745)\r\nCaused by: java.lang.IllegalArgumentException: A universal match pattern ('/**') is defined  before other patterns in the filter chain, causing them to be ignored. Please check the ordering in your <security:http> namespace or FilterChainProxy bean configuration\r\n\tat org.springframework.security.config.http.DefaultFilterChainValidator.checkPathOrder(DefaultFilterChainValidator.java:68)\r\n\tat org.springframework.security.config.http.DefaultFilterChainValidator.validate(DefaultFilterChainValidator.java:55)\r\n\tat org.springframework.security.web.FilterChainProxy.afterPropertiesSet(FilterChainProxy.java:168)\r\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642)\r\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)\r\n\t... 22 more\r\n\r\n```\r\n\r\n### Expected Behavior\r\n\r\nWe want Spring security to load security context configuration from multiple files and merge them in a coherent way. In our example `/rest/jira/webhook/**` should disable all security (authentication and CSRF check)\r\n\r\n### Configuration\r\n\r\n- platform-security-context.xml\r\n\r\n    <http auto-config=\"false\" use-expressions=\"true\" access-decision-manager-ref=\"accessDecisionManager\">\r\n\r\n        <headers>\r\n            <xss-protection />\r\n            <hsts />\r\n            <frame-options policy=\"SAMEORIGIN\" />\r\n        </headers>\r\n\r\n        <access-denied-handler ref=\"authenticationHandler\" />\r\n        <intercept-url pattern=\"/login*\" access=\"permitAll\" />\r\n        <intercept-url pattern=\"/secure/admin/**\" access=\"isAuthenticated()\" />\r\n        <intercept-url pattern=\"/secure/**\" access=\"isAuthenticated()\" />\r\n        <intercept-url pattern=\"/logout\" access=\"permitAll\" />\r\n\r\n        <http-basic />\r\n        <form-login login-page=\"/login\" default-target-url=\"/secure\" authentication-failure-url=\"/login?login_error=1\" always-use-default-target=\"false\"\r\n            authentication-success-handler-ref=\"authenticationHandler\" authentication-failure-handler-ref=\"authenticationHandler\" />\r\n\r\n        <logout invalidate-session=\"true\" logout-url=\"/logout\" success-handler-ref=\"logoutSuccessHandler\" />\r\n\r\n        <custom-filter position=\"PRE_AUTH_FILTER\" ref=\"preauthFilter\" />\r\n        <!-- enable csrf protection -->\r\n        <csrf disabled=\"false\" />\r\n        <session-management invalid-session-url=\"/login\" session-fixation-protection=\"migrateSession\">\r\n            <concurrency-control expired-url=\"/login\" />\r\n        </session-management>\r\n    </http>\r\n\r\n - yankee-security-contest (does NOT work)\r\n\r\n    <http security=\"none\" pattern=\"/rest/jira/webhook/**\" />\r\n\r\n - charlie-security-context (usually WORKS, but at some random times it did not)\r\n\r\n    <http security=\"none\" pattern=\"/rest/jira/webhook/**\" />\r\n\r\nAs you can see, `charlie` is alphabetically before `platform`, but `yankee` comes after\r\n\r\n### Version\r\n\r\n4.2.0.RELEASE\r\n\r\n### Sample\r\n\r\nTBD\r\n"}}
{"actor":{"display_login":"djechelon"}}