Saturday, June 29, 2019

How to enable Spring Security in Java Web application?

Spring Security is one of the most popular open source frameworks to implement security in Java web application 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. In order to enable Spring security in Java Web application, you need to do 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 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 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 important to know and understand the Spring framework before jumping into Spring Security and if you feel you don't have enough knowledge of Spring framework then I suggest you to first go through a comprehensive course like Spring Framework 5: Beginner to Guru on Udemy before starting with Spring Security.





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 Servlet container and initialized and when a request comes upon it call the doFilter() method of DelegatingSpringSecurity. The filter 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. You can further join Learn Spring Security 4 Basic hands-on to learn more about how exactly delegating filter proxy works in Spring security and how to customize and configure its behavior.

How to enable Spring Security in Java Web application



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 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, I suggest you take a look at Spring Security Master class by Eugen Paraschive, it's one of the most up-to-date Spring security course, updated for Spring Security 5.

How to setup Spring Security in Java Web application?


Now, if you hit the URL to login into the admin section, you will be asked to enter username and password and only after correct credentials you will be allowed to access the protected section or pages.

The order on which this <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 complex 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 to a secure one.

If you want to learn more about Spring security, I suggest you join Eugen Paraschive's Spring Security Certification class. Eugen has some good real-world experience on implementing security in complex systems and you will benefit from his experience by joining this class.

Further Reading
Spring Framework 5: Beginner to Guru
Spring Master Class - Beginner to Expert
Spring Security Fundamentals by Bryan Hassen


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)
  • What is the use of DispatcherServlet in Spring MVC? (answer)
  • 15 Spring Boot Interview Questions for Java Programmers (questions)
  • Does Spring certification help in Job and Career? (article)
  • Top 5 Spring Certification Mock Exams (list)
  • 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)

P.S. - If you want to learn how to develop RESTful Web Service using Spring MVC in depth, I suggest you join the REST with Spring master class by Eugen Paraschiv. One of the best course to learn REST with Spring MVC. 

4 comments :

Hearty Raphael said...

Can you please write on the topic of Spring SAML integration

Javin Paul said...

Hello @Hearty, sure, I will write on Spring SAML, but it will take some time, so please be with us.

Unknown said...

Can you please write on the topic of Spring SAML integration

javin paul said...

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