在java应用程序中实现CSRF的错误

时间:2017-09-26 18:29:56

标签: java csrf csrf-protection

您好,
  我试图阻止我的CSR应用程序的Web应用程序。我按照这个链接
 https://dzone.com/articles/preventing-csrf-java-web-apps.To的链接在Java中实现此机制我选择使用两个过滤器,一个用于为每个请求创建令牌/ salt,另一个用于验证它。由于用户请求以及应该验证的后续POST或GET不一定按顺序执行,因此我决定使用基于时间的缓存来存储有效盐字符串的列表。第一个过滤器,用于为请求生成新令牌并将其存储在缓存中。我将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 个答案:

答案 0 :(得分:1)

请使用HttpSession添加属性,因为您必须使用csrfToken    在不同的请求。

Found prime: 5
Found prime: 7
Found prime: 11
Found prime: 13
Found prime: 17
Found prime: 19
Found prime: 23
Found prime: 29
Found prime: 31
Found prime: 37
Found prime: 41
Found prime: 43
Found prime: 47
Found prime: 53
Found prime: 59
Found prime: 61
Found prime: 67
# ........ more