Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   * 
   *      http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.apache.catalina.filters;
 
 import static org.jboss.web.CatalinaMessages.MESSAGES;
 
 import java.util.Map;
 import java.util.Set;
 
Provides basic CSRF protection for a web application. The filter assumes that:
 
 public class CsrfPreventionFilter extends FilterBase {
 
     private String randomClass = SecureRandom.class.getName();
     
     private Random randomSource;
 
     private final Set<StringentryPoints = new HashSet<String>();
     
     private int nonceCacheSize = 5;

    
Entry points are URLs that will not be tested for the presence of a valid nonce. 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.
 
     public void setEntryPoints(String entryPoints) {
         String values[] = entryPoints.split(",");
         for (String value : values) {
             this..add(value.trim());
         }
     }

    
Sets the number of previously issued nonces that will be cached on a LRU basis to support parallel requests, limited use of the refresh and back in the browser and similar behaviors that may result in the submission of a previous nonce rather than the current one. If not set, the default value of 5 will be used.

Parameters:
nonceCacheSize The number of nonces to cache
 
     public void setNonceCacheSize(int nonceCacheSize) {
         this. = nonceCacheSize;
     }
    
    
Specify the class to use to generate the nonces. Must be in instance of java.util.Random.

Parameters:
randomClass The name of the class to use
 
     public void setRandomClass(String randomClass) {
         this. = randomClass;
     }
 
    @Override
    public void init(FilterConfig filterConfigthrows ServletException {
        // Set the parameters
        super.init(filterConfig);
        
        try {
            Class<?> clazz = Class.forName();
             = (Randomclazz.newInstance();
        } catch (ClassNotFoundException e) {
            ServletException se = new ServletException(.cannotCreateRandom(), e);
            throw se;
        } catch (InstantiationException e) {
            ServletException se = new ServletException(.cannotCreateRandom(), e);
            throw se;
        } catch (IllegalAccessException e) {
            ServletException se = new ServletException(.cannotCreateRandom(), e);
            throw se;
        }
    }
    @Override
    public void doFilter(ServletRequest requestServletResponse response,
            FilterChain chainthrows IOExceptionServletException {
        ServletResponse wResponse = null;
        
        if (request instanceof HttpServletRequest &&
                response instanceof HttpServletResponse) {
            
            HttpServletRequest req = (HttpServletRequestrequest;
            HttpServletResponse res = (HttpServletResponseresponse;
            boolean skipNonceCheck = false;
            
            if (..equals(req.getMethod())) {
                String path = req.getServletPath();
                if (req.getPathInfo() != null) {
                    path = path + req.getPathInfo();
                }
                
                if (.contains(path)) {
                    skipNonceCheck = true;
                }
            }
            HttpSession session = req.getSession(false);
            @SuppressWarnings("unchecked")
            LruCache<StringnonceCache = (session == null) ? null :
                (LruCache<String>) session.getAttribute(
                    .);
            
            if (!skipNonceCheck) {
                String previousNonce =
                    req.getParameter(.);
                if (nonceCache == null || previousNonce == null 
                        || !nonceCache.contains(previousNonce)) {
                    res.sendError(.);
                    return;
                }
            }
            
            if (nonceCache == null) {
                nonceCache = new LruCache<String>();
                if (session == null) {
                    session = req.getSession(true);
                }
                session.setAttribute(
                        .nonceCache);
            }
            
            String newNonce = generateNonce();
            
            nonceCache.add(newNonce);
            
            wResponse = new CsrfResponseWrapper(resnewNonce);
        } else {
            wResponse = response;
        }
        
        chain.doFilter(requestwResponse);
    }

    
Generate a once time token (nonce) for authenticating subsequent requests. This will also add the token to the session. The nonce generation is a simplified version of ManagerBase.generateSessionId().
    protected String generateNonce() {
        byte random[] = new byte[16];
        // Render the result as a String of hexadecimal digits
        StringBuilder buffer = new StringBuilder();
        .nextBytes(random);
       
        for (int j = 0; j < random.lengthj++) {
            byte b1 = (byte) ((random[j] & 0xf0) >> 4);
            byte b2 = (byte) (random[j] & 0x0f);
            if (b1 < 10)
                buffer.append((char) ('0' + b1));
            else
                buffer.append((char) ('A' + (b1 - 10)));
            if (b2 < 10)
                buffer.append((char) ('0' + b2));
            else
                buffer.append((char) ('A' + (b2 - 10)));
        }
        return buffer.toString();
    }
    protected static class CsrfResponseWrapper
            extends HttpServletResponseWrapper {
        private String nonce;
        public CsrfResponseWrapper(HttpServletResponse responseString nonce) {
            super(response);
            this. = nonce;
        }
        @Override
        @Deprecated
        public String encodeRedirectUrl(String url) {
            return encodeRedirectURL(url);
        }
        @Override
        public String encodeRedirectURL(String url) {
            return addNonce(super.encodeRedirectURL(url));
        }
        @Override
        @Deprecated
        public String encodeUrl(String url) {
            return encodeURL(url);
        }
        @Override
        public String encodeURL(String url) {
            return addNonce(super.encodeURL(url));
        }
        
        
Return the specified URL with the nonce added to the query string.

Parameters:
url URL to be modified
nonce The nonce to add
        private String addNonce(String url) {
            if ((url == null) || ( == null))
                return (url);
            String path = url;
            String query = "";
            String anchor = "";
            int pound = path.indexOf('#');
            if (pound >= 0) {
                anchor = path.substring(pound);
                path = path.substring(0, pound);
            }
            int question = path.indexOf('?');
            if (question >= 0) {
                query = path.substring(question);
                path = path.substring(0, question);
            }
            StringBuilder sb = new StringBuilder(path);
            if (query.length() >0) {
                sb.append(query);
                sb.append('&');
            } else {
                sb.append('?');
            }
            sb.append(.);
            sb.append('=');
            sb.append();
            sb.append(anchor);
            return (sb.toString());
        }
    }
    
    private static class LruCache<T> {
        // Although the internal implementation uses a Map, this cache
        // implementation is only concerned with the keys.
        private final Map<T,T> cache;
        
        public LruCache(final int cacheSize) {
             = new LinkedHashMap<T,T>() {
                private static final long serialVersionUID = 1L;
                @Override
                protected boolean removeEldestEntry(Map.Entry<T,T> eldest) {
                    if (size() > cacheSize) {
                        return true;
                    }
                    return false;
                }
            };
        }
        
        public void add(T key) {
            .put(keynull);
        }
        
        public boolean contains(T key) {
            return .containsKey(key);
        }
    }
New to GrepCode? Check out our FAQ X