代码之家  ›  专栏  ›  技术社区  ›  shilpa_M

在java应用程序中实现CSRF时出错

  •  1
  • shilpa_M  · 技术社区  · 7 年前

    你好
    我试图阻止我的web应用程序使用CSRF。我点击了这个链接
    链接 https://dzone.com/articles/preventing-csrf-java-web-apps.To 在Java中实现这个机制,我选择使用两个过滤器,一个用于为每个请求创建令牌/salt,另一个用于验证它。由于应该验证的用户请求和后续POST或get不一定按顺序执行,因此我决定使用基于时间的缓存来存储有效salt字符串的列表。第一个过滤器,用于为请求生成新令牌并将其存储在缓存中。我将validateetoken中的令牌值设置为null。你能告诉我什么地方不对吗。我的控制台中的日志包括:

    Checking cache befor creating it from Request :csrfPreventionCache: null
    After setting the csrfPreventionCache to HttpReq
    --------csrfPreventionCache------ :com.google.common.cache.LocalCache$LocalManualCache@254e3d6
    Before going to validate token checking for token in request
     httpReq.getAttribute(csrfToken) ----:DsJiKiGq9BTrLOtA2SzgSYuEnlD
    I am in ValidateToken : csrfToken: null
    csrfPreventionCache is  com.google.common.cache.LocalCache$LocalManualCache@254e3d6
    <Sep 26, 2017 12:21:38 PM EDT> <Error> <HTTP> <BEA-101020> <[ServletContext@2065349032[app:common module:commonWebApp path:null spec-version:3.1]] Servlet failed with an Exception
    java.lang.NullPointerException
        at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:191)
        at com.google.common.cache.LocalCache.getIfPresent(LocalCache.java:3988)
        at com.google.common.cache.LocalCache$LocalManualCache.getIfPresent(LocalCache.java:4783)
        at com.freddiemac.msof.fire.common.ui.report.actions.ValidateCSRFToken.doFilter(ValidateCSRFToken.java:37)
        at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:78)
        Truncated. see log file for complete stacktrace
    
    
       CSRFToken.java     
            package com.test.fire.common.ui.report.actions;
    
            import java.io.IOException;
            import java.util.Random;
            import java.util.concurrent.TimeUnit;
    
            import javax.servlet.Filter;
            import javax.servlet.FilterChain;
            import javax.servlet.FilterConfig;
            import javax.servlet.ServletException;
            import javax.servlet.ServletRequest;
            import javax.servlet.ServletResponse;
            import javax.servlet.http.HttpServletRequest;
    
            import org.apache.commons.lang.RandomStringUtils;
    
            import com.google.common.cache.Cache;
            import com.google.common.cache.CacheBuilder;
    
            public class CSRFToken implements Filter{
    
                @SuppressWarnings("unchecked")
                public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                    // Assuming, its HTTP
                    HttpServletRequest httpReq = (HttpServletRequest) request;
    
                    // Check the user session for the cache, if none is present we create one
                    Cache<String, Boolean> csrfPreventionCache = (Cache<String, Boolean>) httpReq.getSession().getAttribute("csrfPreventionCache");
                    System.out.println("Checking cache befor creating it from Request :csrfPreventionCache: "+csrfPreventionCache);
    
                    if (csrfPreventionCache == null){
                        csrfPreventionCache = CacheBuilder.newBuilder()
                                .maximumSize(5000)
                                .expireAfterWrite(20, TimeUnit.MINUTES)
                                .build();
                        httpReq.getSession().setAttribute("csrfPreventionCache", csrfPreventionCache);
                         System.out.println("After setting the csrfPreventionCache to HttpReq");
                         System.out.println("--------csrfPreventionCache------ :"+httpReq.getSession().getAttribute("csrfPreventionCache"));
                    }
                    // Generate the csrfToken and store it in the users cache
                    String csrfToken = RandomStringUtils.random(27, 0, 0, true, true, null, new Random());
                    csrfPreventionCache.put(csrfToken, Boolean.TRUE);
    
                    // Add the token to the current request so it can be used by the page rendered in this request
                    httpReq.setAttribute("csrfToken", csrfToken);
                    System.out.println("Before going to validate token checking for token in request");
                    System.out.println(" httpReq.getAttribute(csrfToken) ----:"+httpReq.getAttribute("csrfToken"));
                    chain.doFilter(request, response);
                }
    
                public void init(FilterConfig filterConfig) throws ServletException {
                //Do Nothing
                }
    
                public void destroy() {
                //Do Nothing
                }
    
            }
    
    
    
    
         Mapping in web.xml 
    
                <servlet-mapping>
            <servlet-name>action</servlet-name>
            <url-pattern>*.do</url-pattern>
          </servlet-mapping>
              <filter>
                <filter-name>csrfToken</filter-name>
                <filter-class>com.test.fire.common.ui.report.actions.CSRFToken</filter-class>
            </filter>
            <filter-mapping>
                <filter-name>csrfToken</filter-name>
                <url-pattern>*.do</url-pattern>
            </filter-mapping>
            <filter>
            <filter-name>validateCSRFToken</filter-name>
            <filter-class>com.test.fire.common.ui.report.actions.ValidateCSRFToken</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>validateCSRFToken</filter-name>
            <url-pattern>*.do</url-pattern>
        </filter-mapping>
    
    
    
    
    
            ValidateToken
    
          package com.test.msof.fire.common.ui.report.actions;
    
        import java.io.IOException;
        import java.util.Random;
        import java.util.concurrent.TimeUnit;
    
        import javax.servlet.Filter;
        import javax.servlet.FilterChain;
        import javax.servlet.FilterConfig;
        import javax.servlet.ServletException;
        import javax.servlet.ServletRequest;
        import javax.servlet.ServletResponse;
        import javax.servlet.http.HttpServletRequest;
    
        import org.apache.commons.lang.RandomStringUtils;
    
        import com.google.common.cache.Cache;
        import com.google.common.cache.CacheBuilder;
    
        public class ValidateCSRFToken implements Filter{
    
            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
    
                // Assume its HTTP
                HttpServletRequest httpReq = (HttpServletRequest) request;
    
                // Get the token sent with the request
                String csrfToken = (String) httpReq.getParameter("csrfToken");
                System.out.println("I am in ValidateToken : csrfToken: "+csrfToken);
    
                // Validate that the token is in the cache
                Cache<String, Boolean> csrfPreventionCache = (Cache<String, Boolean>)
                    httpReq.getSession().getAttribute("csrfPreventionCache");
                System.out.println("csrfPreventionCache is  "+csrfPreventionCache);
                System.out.println("csrfPreventionCache.getIfPresent(csrfToken) is  "+csrfPreventionCache.getIfPresent(csrfToken));
    
                if (csrfPreventionCache != null &&
                        csrfToken != null &&
                        csrfPreventionCache.getIfPresent(csrfToken) != null){
    
                    // If the token is in the cache, we move on
                    chain.doFilter(request, response);
                } else {
                    // Otherwise we throw an exception aborting the request flow
                    throw new ServletException("Potential CSRF detected!!.");
                }
            }
    
            @Override
            public void init(FilterConfig arg0) throws ServletException {
            }
    
            @Override
            public void destroy() {
            }
        }
    
    
    
    
        jsp - Added the below entry as a hidden variable
    
    
    
     <%@ page info="reportBody"%>
    
        <%@ taglib uri="/tags/struts-bean" prefix="bean" %>
        <%@ taglib uri="/tags/struts-logic" prefix="logic" %>
        <%@ taglib uri="/tags/struts-html" prefix="html" %>
    
    
    
        <%--<table background="/vaeWebApp/images/a1.gif" border="0" cellspacing="0" cellpadding="0" width="100%" height="100%"> --%>
        <table border="0" cellspacing="0" cellpadding="0" width="100%" height="100%">
         <logic:iterate id="appListForm" 
                name="appReportHomeForm" 
                property="appListForms"
                indexId="contIndex"
                type="com.freddiemac.msof.fire.common.ui.report.forms.AppListForm"
              >
            <%
              String ind = "appListForms["+contIndex+"].";
              System.out.println("ind:" + ind); 
              <input type="hidden" name="csrfToken" value="<c:out value='${csrfToken}'/>"/>
            %>
            <tr>
                <td>
                      <u><h2>
                      <html:link href="appReportListHome.do" name="appReportHomeForm" property='<%= ind+"parameters" %>'>
                         <bean:write name="appReportHomeForm" property='<%= ind+"appDesc" %>' /> 
                      </html:link>
                      </h2></u>
                </td>
    
    
            </tr>
            <tr>
          <td>
        <p>
            <%-- {Describe more about specific report here} --%>
        </p>
          </td
         </tr>
        </logic:iterate>
    
    
    
          </td
         </tr>
    
        </table>
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Kamal Chanda    7 年前

    请使用HttpSession添加属性,因为您必须使用csrfToken

         HttpSession session=request.getSession();  //in CSRFToken class
         session.setAttribute("csrfToken",csrfToken);  
    
         HttpSession session=request.getSession(false);  // in ValidateCSRFToken
         String csrfToken=(String)session.getAttribute("csrfToken");