Spring Security is one of the most popular open-source frameworks to implement security in Java web applications in a declarative way. It provides several essential security features like LDAP authentication, authorization, role-based access control, remembers the password, URL protection, concurrent active sessions management, etc. To enable Spring security in Java Web application, you need to configure three things - declare a delegating proxy filter in web.xml, add the ContextLoaderListener in web.xml and provide actual security constraints on applicationContext-Security.xml file. Since Spring security uses a chain of filters to implement various security constraints, also known as Spring's "security chain filter", it relies on web container for the initialization of delegating filter proxy.
If you remember, filters are created, maintained, and destroyed by a Servlet container like Tomcat or Jetty. You declare filters in web.xml, and the web container initializes them by calling their init(FilterConfig config) method. This filter then delegates the actual pre-processing and post-processing task to Spring aware Filter implementations provided by the Spring Security framework.
Every time a request or response comes and matches the URL pattern of the filter, then the Servlet container calls the DelegatingFilterProxy's doFilter() method for the request and response filtering.
This method has access to ServletRequest, ServletResponse, and a FilterChain object, which means it can modify request headers, response headers, and response body before sending the request to Servlet or response to Client. The FilterChain object is used to route the request to another filter in the chain for further processing.
Btw, it's essential to know and understand the Spring framework before jumping into Spring Security, and if you feel you don't have enough knowledge of the Spring framework then I suggest you first learn Spring Framework before using Spring Security. Spring documentation is also very good to learn about spring in depth.
Here are the essential steps to enable Spring Security features in your Java web application:
1) Declare DelegatingFilterProxy filter in web.xml
2) Specify the Spring application context file to ContextLoaderListener
3) Specify Spring Security intercept URL pattern in the applicationContext-Security.xml file
Here is how a DelegatingFilterProxy filter declaration looks like in web.xml
This filter is then picked up by the Servlet container and initialized, and when a request comes upon, it calls the doFilter() method of DelegatingSpringSecurity. The screen is initialized by calling the init() method. The DelegatingFilterProxy extends GenricFilterBean, which implements the init(FilterConfig filterConfig) method and give a call back to initFilterBean() to allow subclasses to perform their initialization.
By default, the DelegatingFilterProxy class will look for a Spring bean with the same name as the filter-name tag in the Spring application context file during initialization, as shown below in the code from the DelegatingFilterProxy class from Spring Security JAR file.
If you want to customize this behavior, you can provide the name of the bean class using targetBeanName via a FilterConfig object. If you don't, then this will use the filter-name which is "springSecurityFilterChain". It then searches for this bean in both applicationContext.xml and applicationContext-Security.xml file for initialization.
But, when you search for this in your configuration file, there is a good chance that you won't find it because of <http auto-config="true">, which hides a lot of complexity by using default values.
If you remember, filters are created, maintained, and destroyed by a Servlet container like Tomcat or Jetty. You declare filters in web.xml, and the web container initializes them by calling their init(FilterConfig config) method. This filter then delegates the actual pre-processing and post-processing task to Spring aware Filter implementations provided by the Spring Security framework.
Every time a request or response comes and matches the URL pattern of the filter, then the Servlet container calls the DelegatingFilterProxy's doFilter() method for the request and response filtering.
This method has access to ServletRequest, ServletResponse, and a FilterChain object, which means it can modify request headers, response headers, and response body before sending the request to Servlet or response to Client. The FilterChain object is used to route the request to another filter in the chain for further processing.
Btw, it's essential to know and understand the Spring framework before jumping into Spring Security, and if you feel you don't have enough knowledge of the Spring framework then I suggest you first learn Spring Framework before using Spring Security. Spring documentation is also very good to learn about spring in depth.
Steps to Activate Spring Security in Web Application.
Here are the essential steps to enable Spring Security features in your Java web application:1) Declare DelegatingFilterProxy filter in web.xml
2) Specify the Spring application context file to ContextLoaderListener
3) Specify Spring Security intercept URL pattern in the applicationContext-Security.xml file
Here is how a DelegatingFilterProxy filter declaration looks like in web.xml
<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>
This filter is then picked up by the Servlet container and initialized, and when a request comes upon, it calls the doFilter() method of DelegatingSpringSecurity. The screen is initialized by calling the init() method. The DelegatingFilterProxy extends GenricFilterBean, which implements the init(FilterConfig filterConfig) method and give a call back to initFilterBean() to allow subclasses to perform their initialization.
By default, the DelegatingFilterProxy class will look for a Spring bean with the same name as the filter-name tag in the Spring application context file during initialization, as shown below in the code from the DelegatingFilterProxy class from Spring Security JAR file.
protected void initFilterBean() throws ServletException { synchronized (this.delegateMonitor) { if (this.delegate == null) { // If no target bean name specified, use filter name. if (this.targetBeanName == null) { this.targetBeanName = getFilterName(); } // Fetch Spring root application context and initialize the // delegate early, if possible. // If the root application context will be started // after this filter proxy, we'll have to resort to lazy // initialization. WebApplicationContext wac = findWebApplicationContext(); if (wac != null) { this.delegate = initDelegate(wac); } } } }
If you want to customize this behavior, you can provide the name of the bean class using targetBeanName via a FilterConfig object. If you don't, then this will use the filter-name which is "springSecurityFilterChain". It then searches for this bean in both applicationContext.xml and applicationContext-Security.xml file for initialization.
But, when you search for this in your configuration file, there is a good chance that you won't find it because of <http auto-config="true">, which hides a lot of complexity by using default values.
Here is how you load the Spring security configuration file in a Java web application:
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext.xml /WEB-INF/applicationContext-security.xml </param-value> </context-param>
The configuration file name is applicationContext-security.xml, and it should be placed inside the WEB-INF directory.
Here is how your sample Spring security config file should look:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" 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-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <security:http auto-config="true"> <security:intercept-url pattern="/admin" access="ROLE_ADMIN" /> </security:http> <security:authentication-manager> <security:authentication-provider> <security:user-service> <security:user authorities="ROLE_ADMIN" name="admin" password="admin" /> <security:user authorities="ROLE_ADMIN" name="root" password="root" /> </security:user-service> </security:authentication-provider> </security:authentication-manager> </beans>
By doing this simple configuration, you have now protected all URLs ending with /admin to be only accessible with username and password. The two users who have access to this are now admin and root. In short, you don't need to code any Spring security filter or bean, all is done magically by using existing Spring security filters and <http auto-config="true"> tag.
Btw, if you want to understand this configuration in-depth like what is each tag means and how they related to Java classes, you can check official Spring Documentation which is now also updated for Spring Security 6.
Now, if you hit the URL to login to the admin section, you will be asked to enter your username and password, and only after the correct credentials, you will be allowed to access the protected section or pages.
The order in which these <intercept-url> patterns are declared matters a lot, and they must be declared in the order of most specific to least specific because these patterns are evaluated in the order they are declared in the spring security application context file, and once a match is found, other patterns are not evaluated.
That's all about how to enable or activate Spring security in a Java Web application. It's really simple to configure and use but very powerful and gives you a lot of options to implement sophisticated security constraints. You can also see that we have introduced security in a rather unobtrusive and declarative way. We haven't written any code, we just did some XML configuration to make an insecure web application a secure one.
Other Spring Articles you may like to explore
- Difference between @RestControler and @Controller in Spring MVC? (answer)
- 23 Spring MVC Interview questions for 2 to 3 years experienced (list)
- Top 5 Courses to Learn Microservices with Spring and Java (courses)
- What is the use of DispatcherServlet in Spring MVC? (answer)
- Spring Security Official Documentation (docs)
- 15 Spring Boot Interview Questions for Java Programmers (questions)
- Does Spring certification help in Job and Career? (article)
- 10 Best Spring Security and OAuth2 Courses (best courses)
- My favorite courses to learn Software Architecture (courses)
- Top 5 Spring Certification Mock Exams (list)
- 10 Advanced Spring Boot Courses for Experienced Java developers (courses)
- 5 Courses to Learn Spring Framework in-depth (courses)
- Difference between @Autowired and @Injection annotations in Spring? (answer)
- 10 Spring MVC Annotations Every Java developer should know (annotations)
- 5 Courses to Learn Spring Boot for Beginners (courses)
- 5 Spring and Hibernate online courses for Java developers (list)
- 10 Free Spring Boot Courses for Beginners (free courses)
4 comments :
Can you please write on the topic of Spring SAML integration
Hello @Hearty, sure, I will write on Spring SAML, but it will take some time, so please be with us.
Can you please write on the topic of Spring SAML integration
Thanks for suggestion @Unknown, I don't much about Spring SAML integration yet but will definitely write when I get a chance to explore that. Keep in touch.
Post a Comment