Spring Security + MVC : Questions around context definition & bean scope
java, spring, spring-mvc, spring-security
Solution
First: the beans defined within `applicationContext.xml` (`ContextLoaderListener`) can not access the one defined in `spring-mvc-servlet.xml` (`DispatcherServlet`) but not the other way around.
You asked:
Given that spring-mvc defines a series of controllers, which I want to mark as @Secured, how will these be processed if the controller is not visible to the security context?
So this works without problems, because the controllers must be defined in the `spring-mvc-servlet.xml`, so they "see" the Spring Security stuff defined in `applicationContext.xml`
Do I need to move my from the servlet.xml to the global applicationContext.xml?
No
Do I need additional configuration within the spring-mvc-servlet.xml to tell it to participate in Spring security?
No
... which leaves the spring-mvc-context.xml almost empty. Is this common?
The `spring-mvc-context.xml` should contain every thing that is related to Web Stuff (except secrutiy). So the common parts of the `spring-mvc-context.xml` are component scan for `@Controller`, some Interceptors (`mvc:interceptors`), `mvc:resources`, `mvc:default-servlet-handler`, `mvc:view-controller`, `ReloadableResourceBundleMessageSource`, `CookieLocaleResolver`, `.SimpleMappingExceptionResolver`...
BTW: If you use component scan, then you need two of them, one at `applicationContext.xml` to scan for `@Service` `@Repository` and `@Component` (But not `@Controller`) and a second in `spring-mvc-context.xml` that only scan for `@Controller`!
@See also this question: ContextLoaderListener or not? It discuss the theme from an other point of view.
Problem
I'm trying to understand the reccommended way for defining Spring Security in Spring-MVC applications, where the bean definitions is split across multiple parent/child contexts. For example, my current app's `web.xml` looks as follows, (which I understand to be fairly standard) ``` <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml /WEB-INF/securityContext.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring-mvc</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> ``` So, I have a standard `ContextLoaderListener` defined at `/`, which loads my global configs - `applicationContext.xml` and `securityContext.xml`. I also define the spring mvc `DispatcherServlet` at `/app/`, which loads it's own beans from `spring-mvc-servlet.xml`. As I understand it, config defined in `spring-mvc-servlet.xml` is not visible to config defined in either of the top-level context files. Where then is the best place to define app-level security concepts? For example, I'd like to add the following filter. ``` <security:http pattern="/oauth/token" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"> <security:custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" /> </security:http> ``` This is so that requests to `/app/oauth/token` pass through this filter, and get basic authentication processed. Because this pertains directly to a concern of the Spring-MVC app, I initially defined it in `spring-mvc-context.xml` (which is why the `app` is excluded from the url). However, this means it's not visible to the security config defined in `securityContext.xml`, so it's ignored. So, I move it up to `securityContext.xml`, but in doing so, also must move all the dependencies. I quickly end up moving everything up to `applicationContext.xml`, which leaves the `spring-mvc-context.xml` almost empty. Is this common? What is the reccomended split between what is defined in top-level contexts, and what gets defined in child contexts? Given that spring-mvc defines a series of controllers, which I want to mark as `@Secured`, how will these be processed if the controller is not visible to the security context? Do I need to move my `<mvc:annotation-driven />` from the `servlet.xml` to the global `applicationContext.xml`? Do I need additional configuration within the `spring-mvc-servlet.xml` to tell it to participate in Spring security? I've read the documentation on Spring-MVC, but there's very few specifics on how to configure this. Additionally, the Spring OAuth examples seem to define everything within a single config file, which doesn't seem very real-world, and seems to contradict other examples I've read.