我正在制作Java Web App。这项技术非常新。我需要在每个服务器请求中实现反CSRF令牌,以便可以使请求成为CSRF攻击安全的对象。我遇到了以下链接:
https://dzone.com/articles/preventing-csrf-java-web-apps
因此,在执行此操作的同时,我创建了如下代码:
LoadSalt.java
public void doFilter(final ServletRequest req,final ServletResponse res,
final FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.addHeader("Access-Control-Allow-Origin","*");
response.addHeader("Allow-Access-Control-Credentials", "true");
response.addHeader("Access-Control-Allow-Methods","POST");
response.addHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
response.addHeader("Access-Control-Max-Age", "1728000");
response.addHeader("X-Content-Type-Options", "nosniff");
response.addHeader("X-XSS-Protection", "1; mode=block"); // on
response.addHeader("X-Frame-Options", "deny");
response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate, private"); // HTTP 1.1.
response.addHeader("Pragma", "no-cache"); // HTTP 1.0.
response.addDateHeader("Expires", 0); // Proxies.
System.out.println(request.getRequestURL());
// Check the user session for the salt cache, if none is present we create one
@SuppressWarnings("unchecked")
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>) request.getSession().getAttribute("csrfPreventionSaltCache");
if (csrfPreventionSaltCache == null)
{
csrfPreventionSaltCache = CacheBuilder.newBuilder().maximumSize(5000).expireAfterWrite(20, TimeUnit.MINUTES).build();
request.getSession().setAttribute("csrfPreventionSaltCache", csrfPreventionSaltCache);
}
// Generate the salt and store it in the users cache
String salt = RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());
csrfPreventionSaltCache.put(salt, Boolean.TRUE);
// Add the salt to the current request so it can be used
// by the page rendered in this request
request.setAttribute("csrfPreventionSalt", salt);
filterChain.doFilter(request, response);
}
ValidateSalt.java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// Assume its HTTP
HttpServletRequest httpReq = (HttpServletRequest) request;
// Get the salt sent with the request
String salt = (String) httpReq.getAttribute("csrfPreventionSalt");
// Validate that the salt is in the cache
@SuppressWarnings("unchecked")
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>) httpReq.getSession().getAttribute("csrfPreventionSaltCache");
if (csrfPreventionSaltCache != null && salt != null && csrfPreventionSaltCache.getIfPresent(salt) != null)
{
// If the salt 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!! Inform a scary sysadmin ASAP.");
}
}
在web.xml中添加了过滤器
<filter>
<filter-name>LoadSalt</filter-name>
<filter-class>com.sample.filter.LoadSalt</filter-class>
</filter>
<filter-mapping>
<filter-name>LoadSalt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<display-name>ValidateSalt</display-name>
<filter-name>ValidateSalt</filter-name>
<filter-class>com.sample.filter.ValidateSalt</filter-class>
</filter>
<filter-mapping>
<filter-name>ValidateSalt</filter-name>
<servlet-name>ControllerServlet</servlet-name>
</filter-mapping>
问题在于,执行请求时,它不会失败。它总是创建一个新的“盐”值。理想情况下,它应该会失败,因为我没有在任何JSP页面中以HTML形式编写以下代码(如上面共享的链接中所述):
<form action="/transferMoneyServlet" method="get">
<input type="hidden" name="csrfPreventionSalt" value="<c:out
value='${csrfPreventionSalt}'/>"/>
...
</form>
有人,请帮助我。预先感谢。