Class CsrfPreventionFilter

  • All Implemented Interfaces:
    javax.servlet.Filter

    public class CsrfPreventionFilter
    extends java.lang.Object
    implements javax.servlet.Filter
    Provides basic CSRF protection implementing a Same Origin Standard Header verification (step 1) and a Synchronization Token with a cookie-stored token on the front-end.
     Positive scenario:
               Client                            Server
                  |                                 |
                  | GET Fetch Request              \| JSESSIONID
                  |---------------------------------| X-CSRF-Token
                  |                                /| pair generation
                  |/Response to Fetch Request       |
                  |---------------------------------|
     JSESSIONID   |\                                |
     X-CSRF-Token |                                 |
     pair cached  | POST Request with valid token  \| JSESSIONID
                  | header                          |
                  |---------------------------------| X-CSRF-Token
                  |                                /| pair validation
                  |/ Response to POST Request       |
                  |---------------------------------|
                  |\                                |
    
     Negative scenario:
               Client                            Server
                  |                                 |
                  | POST Request without token      | JSESSIONID
                  | header                         \| X-CSRF-Token
                  |---------------------------------| pair validation
                  |                                /|
                  |/Request is rejected             |
                  |---------------------------------|
                  |\                                |
    
               Client                            Server
                  |                                 |
                  | POST Request with invalid token\| JSESSIONID
                  |---------------------------------| X-CSRF-Token
                  |                                /| pair validation
                  |/Request is rejected             |
                  |---------------------------------|
                  |\                                |
     
    Parts of this code were ported from the CsrfPreventionFilter class of Apache Tomcat. Furthermore, the RestCsrfPreventionFilter class from the same codebase was used as a guideline.
    Author:
    Nikola Koevski
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void destroy()  
      void doFilter​(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain filterChain)  
      protected boolean doSameOriginStandardHeadersVerification​(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
      Validates if the Origin/Referer header matches the provided target origin.
      protected boolean doTokenValidation​(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
      Validates the provided CSRF token value from the request with the session CSRF token value.
      protected java.lang.String generateCSRFToken()
      Generate a one-time token for authenticating subsequent requests.
      protected java.lang.String getCookiePath​(javax.servlet.http.HttpServletRequest request)  
      int getDenyStatus()  
      java.lang.String getRandomClass()  
      java.net.URL getTargetOrigin()  
      void init​(javax.servlet.FilterConfig filterConfig)  
      protected boolean isNonModifyingRequest​(javax.servlet.http.HttpServletRequest request)
      Determine if the request a non-modifying request.
      protected void setCSRFToken​(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
      Generates a new CSRF Token which is persisted in the session.
      void setDenyStatus​(int denyStatus)
      Sets the response status code that is used to reject denied request.
      void setEntryPoints​(java.lang.String entryPoints)
      Entry points are URLs that will not be tested for the presence of a valid token.
      void setRandomClass​(java.lang.String randomClass)
      Sets the name of the class to use to generate tokens.
      void setTargetOrigin​(java.lang.String targetOrigin)
      Target origin is the application expected deployment domain, i.e.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • entryPoints

        protected final java.util.Set<java.lang.String> entryPoints
    • Constructor Detail

      • CsrfPreventionFilter

        public CsrfPreventionFilter()
    • Method Detail

      • init

        public void init​(javax.servlet.FilterConfig filterConfig)
                  throws javax.servlet.ServletException
        Specified by:
        init in interface javax.servlet.Filter
        Throws:
        javax.servlet.ServletException
      • doFilter

        public void doFilter​(javax.servlet.ServletRequest servletRequest,
                             javax.servlet.ServletResponse servletResponse,
                             javax.servlet.FilterChain filterChain)
                      throws java.io.IOException,
                             javax.servlet.ServletException
        Specified by:
        doFilter in interface javax.servlet.Filter
        Throws:
        java.io.IOException
        javax.servlet.ServletException
      • doTokenValidation

        protected boolean doTokenValidation​(javax.servlet.http.HttpServletRequest request,
                                            javax.servlet.http.HttpServletResponse response)
                                     throws java.io.IOException
        Validates the provided CSRF token value from the request with the session CSRF token value.
        Parameters:
        request -
        response -
        Returns:
        true if the token is valid
        Throws:
        java.io.IOException
      • doSameOriginStandardHeadersVerification

        protected boolean doSameOriginStandardHeadersVerification​(javax.servlet.http.HttpServletRequest request,
                                                                  javax.servlet.http.HttpServletResponse response)
                                                           throws java.io.IOException
        Validates if the Origin/Referer header matches the provided target origin.
        Parameters:
        request -
        response -
        Returns:
        true if the values match
        Throws:
        java.io.IOException
      • setCSRFToken

        protected void setCSRFToken​(javax.servlet.http.HttpServletRequest request,
                                    javax.servlet.http.HttpServletResponse response)
        Generates a new CSRF Token which is persisted in the session. How the token is forwarded to the client and how it will be persisted there is not covered by this method.
        Parameters:
        request -
      • getCookiePath

        protected java.lang.String getCookiePath​(javax.servlet.http.HttpServletRequest request)
      • getTargetOrigin

        public java.net.URL getTargetOrigin()
      • setTargetOrigin

        public void setTargetOrigin​(java.lang.String targetOrigin)
                             throws java.net.MalformedURLException
        Target origin is the application expected deployment domain, i.e. the domain name through which the webapps are accessed. If nothing is set, the "Same Origin with Standard Headers" verification is not performed.
        Parameters:
        targetOrigin - The application's domain name together with the protocol and port (ex. http://example.com:8080)
        Throws:
        java.net.MalformedURLException
      • setEntryPoints

        public void setEntryPoints​(java.lang.String entryPoints)
        Entry points are URLs that will not be tested for the presence of a valid token. They are used to provide a way to navigate back to a protected application after navigating away from it. Entry points will be limited to HTTP GET requests and should not trigger any security sensitive actions.
        Parameters:
        entryPoints - Comma separated list of URLs to be configured as entry points.
      • getDenyStatus

        public int getDenyStatus()
        Returns:
        the response status code that is used to reject a denied request.
      • setDenyStatus

        public void setDenyStatus​(int denyStatus)
        Sets the response status code that is used to reject denied request. If none is set, the default value of 403 will be used.
        Parameters:
        denyStatus - HTTP status code
      • getRandomClass

        public java.lang.String getRandomClass()
      • setRandomClass

        public void setRandomClass​(java.lang.String randomClass)
        Sets the name of the class to use to generate tokens. The class must be an instance of `java.util.Random`. If not set, the default value of `java.security.SecureRandom` will be used.
        Parameters:
        randomClass - The name of the class
      • destroy

        public void destroy()
        Specified by:
        destroy in interface javax.servlet.Filter
      • isNonModifyingRequest

        protected boolean isNonModifyingRequest​(javax.servlet.http.HttpServletRequest request)
        Determine if the request a non-modifying request. A non-modifying request is one that is either a 'HTTP GET/OPTIONS/HEAD' request, or is allowed explicitly through the 'entryPoints' parameter in the web.xml
        Returns:
        true if the request is a non-modifying request
      • generateCSRFToken

        protected java.lang.String generateCSRFToken()
        Generate a one-time token for authenticating subsequent requests.
        Returns:
        the generated token