The following is a good article from the Internet! However, what I cannot understand is why such a good article has to block people out of the country! Cannot figure out ...... Simple Web application with spring security: Part 13
In the last few pages on Spring Security Series, I was about to tackle method-level security and domain-instance security using spring security; but before doing this, I am going to go back to basics and have e the basics of spring security in a deeper
Way.
Back to Basics
We are going to revert to simplest configuration first of all:
In ourSpringsecuritywebapp-servlet.xmlFile, we remove the configuration for the acldemocontroller for now and any reference to it within the file.
In ourWeb. xml:
We configure a listener to load the context of the Web application at start up. This will load our applicationContext-security.xml file.
We register a filter namedSpringsecurityfilterchainThat delegates all requests matching the URL pattern '/*' To A delegatingfilterproxy.
<!--- Location of the XML file that defines the root application context -Applied by ContextLoaderListener.--><context-param><param-name>contextConfigLocation</param-name><param-value> WEB-INF\applicationContext-security.xml </param-value></context-param><!--- Loads the root application context of this web app at startup. - Theapplication context is then available via -WebApplicationContextUtils.getWebApplicationContext(servletContext).--><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>
In ourApplicationContext-security.xmlWe leave it empty like so:
<?xml version="1.0" encoding="UTF-8"?><beans:beans xmlns="http://www.springframework.org/schema/security"xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"></beans:beans>
Build and deploy
The application builds OK and deploys to Tomcat. However it fails when starting up on Tomcat due:
SEVERE: Error filterStartSEVERE: Context [/springsecuritywebapp] startup failed due to previous errors
Looking in the Tomcat logs we see the following error:
23/12/2008 18:33:28 org.apache.catalina.core.StandardContext filterStartSEVERE: Exception starting filter springSecurityFilterChainorg.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' is definedat org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:971)at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:246)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:168)at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:884)at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:216)at org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:145)at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:179)
Clearly the problem is that we haven't configured any bean named 'springsecurityfilterchain '.
Fixing springsecurityfilterchain Problem
If we use the
We update our applicationContext-security.xml to look like so:
When we build and deploy this we get another problem:
org.apache.catalina.core.StandardContext listenerStartSEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListenerorg.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: No AuthenticationEntryPoint could be established. Please make sure you have a login mechanism configured through the namespace (such as form-login) or specify a custom AuthenticationEntryPoint with the custom-entry-point-ref attributeOffending resource: ServletContext resource [/WEB-INF/applicationContext-security.xml]at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:72)
So spring security is failing fast as it expects us to have some form of authentication mechanism:
We update our applicationContext-security.xml to look like so:
Building and deploy, we see another problem reported on Tomcat:
org.apache.catalina.core.StandardContext listenerStartSEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListenerorg.springframework.beans.factory.BeanCreationException: Error creating bean with name '_authenticationManager': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: No authentication providers were found in the application context
So spring Security expectsAuthentication providerTo be configured to facilitate the form login via
AuthenticationmanagerThat is being automatically created by spring security and named
_ Authenticationmanager.
So we update the our applicationContext-security.xml again to add the following snippet:
<authentication-provider> <user-service id="userDetailsService"> <user password="password" name="username" authorities="ROLE_USER" /> </user-service></authentication-provider>
Building and deploying again, we see from the Tomcat logs that the application has started successfully. The Authentication through form login (which is all we have configured) works as it shound.
How it works behind the scenes
When the applications starts correctly using the configuration laid out as above, see from the Tomcat logs the following details:
INFO: Pre-instantiating singletons inorg.springframework.beans.factory.support.DefaultListableBeanFactory@195afdb: defining beans[_authenticationManager,_filterChainProxy,_httpSessionContextIntegrationFilter,_filterChainProxyPostProcessor,_filterChainList,_securityContextHolderAwareRequestFilter,_accessManager,_portMapper,_exceptionTranslationFilter,_filterSecurityInterceptor,_formLoginFilter,_formLoginEntryPoint,_entryPointInjectionBeanPostProcessor,_userServiceInjectionPostProcessor,org.springframework.security.providers.dao.DaoAuthenticationProvider#0,userDetailsService,org.springframework.security.config.AuthenticationProviderBeanDefinitionParser$AuthenticationProviderCacheResolver#0]; root of factory hierarchy
What is happening is that from that small amount of configuration, spring security is instantiating a number of beans to enable the functionality. Of special interest is
_ Filterchainproxy. From the logs, we see the filterchainproxy is configured:
INFO: FilterChainProxy: FilterChainProxy[UrlMatcher = org.springframework.security.util.AntUrlPathMatcher[requiresLowerCase='true']; Filter Chains: {/**=[org.springframework.security.context.HttpSessionContextIntegrationFilter[ order=200; ],org.springframework.security.ui.webapp.AuthenticationProcessingFilter[ order=700; ],org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter[ order=1100; ],org.springframework.security.ui.ExceptionTranslationFilter[ order=1400; ],org.springframework.security.intercept.web.FilterSecurityInterceptor@1cd6a32]}]Following a HTTP Request
As an example, I try to visit the following page on the application:Http: // localhost: 8080/springsecuritywebapp/login. jsp. This requests starts off its journey navigating through the Apache Tomcat container:
Apache javasatsApplicationfilterchain. dointernalchainMethod retrieves filter configured in our web. xml.
Applicationfilterconfig [name = springsecurityfilterchain, filterclass = org. springframework. Web. Filter. delegatingfilterproxy]
It then uses the filter[Of Type
Delegatingfilterproxy]And invokesDofilterOn this passing the request and response types. As the delegatingfilterproxy's javadoc states:
This approach is special useful for filter implementation with complex setup needs, allowing to apply the full spring bean definition machinery to filter instances. Alternatively, consider standard filter setup in combination with looking up service
Beans from the spring root application context.
And this is its purpose here, to delegate to
Filterchainproxy for which a bean is already instantiated (_ Filterchainproxy). This is then responsible for filtering the request through each of filters that are part of its
Virtualfilterchain.
From our initial configuration set up for spring security, we have five filters that are part
FilterchainproxySVirtualfilterchain. These are in order of execution:
HttpSessionContextIntegrationFilter
AuthenticationProcessingFilter
SecurityContextHolderAwareRequestFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
In the next part I will talk about what happens to our request to reachHttp: // localhost: 8080/springsecuritywebapp/login. jsp
In each of these filters.