gpt4 book ai didi

java - 如何防止我的网络应用程序在 Java 中受到 CSRF(跨站点请求伪造)

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:53:33 25 4
gpt4 key购买 nike

我正在尝试防止我的 Web 应用程序遭受 CSRF(跨站点请求伪造)我点击了这个链接 Link for CSRF

这是我试过的。为了在 Java 中实现这种机制,我选择使用两个过滤器,一个为每个请求创建盐,另一个用于验证它。由于用户请求和后续应验证的 POST 或 GET 不一定按顺序执行,我决定使用基于时间的缓存来存储有效盐字符串列表。

第一个过滤器,用于为请求生成新的盐并将其存储在缓存中,可以编码如下:

public class LoadSalt implements Filter{


public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

// Assume its HTTP
HttpServletRequest httpReq = (HttpServletRequest)request;
// Check the user session for the salt cache, if none is present we create one
@SuppressWarnings("unchecked")
Cache<String, Boolean> csrfPreventionSaltCache = (Cache<String, Boolean>)
httpReq.getSession().getAttribute("csrfPreventionSaltCache");

System.out.println("Checking cahce befor creating it from Request :csrfPreventionSaltCache: "+csrfPreventionSaltCache);

if(csrfPreventionSaltCache == null)
{
System.out.println("csrfPreventionSaltCache is null have to create new one");
String csrfPreventionfromrequest = (String) httpReq.getSession().getAttribute("csrfPreventionSaltCache");
System.out.println("csrfPreventionfromrequest :"+csrfPreventionfromrequest);

// creating a new cache
csrfPreventionSaltCache = CacheBuilder.newBuilder().maximumSize(5000)
.expireAfterAccess(20, TimeUnit.MINUTES).build();

// Setting to gttpReq
httpReq.getSession().setAttribute("csrfPreventionSaltCache", csrfPreventionSaltCache);

System.out.println("After setting the csrfPreventionSaltCache to HttpReq");
System.out.println("--------csrfPreventionSaltCache------ :"+httpReq.getSession().getAttribute("csrfPreventionSaltCache"));
}



// Generate the salt and store it in the users cache
String salt = RandomStringUtils.random(20, 0, 0, true, true, null, new SecureRandom());
System.out.println("Salt: "+salt);
csrfPreventionSaltCache.put(salt, Boolean.TRUE);
// Add the salt to the current request so it can be used
// by the page rendered in this request
httpReq.setAttribute("csrfPreventionSalt", salt);

System.out.println("Before going to validate salt checking for salt in request");
System.out.println(" httpReq.getAttribute(csrfPreventionSalt) ----:"+httpReq.getAttribute("csrfPreventionSalt"));
// System.out.println(" httpReq.getSession().getAttribute(csrfPreventionSalt) :----"+httpReq.getSession().getAttribute("csrfPreventionSalt"));


chain.doFilter(request, response);
}
public void init(FilterConfig arg0) throws ServletException {

}

public void destroy() {

}
}

web.xml 中的映射

        <filter>
<filter-name>loadSalt</filter-name>
<filter-class>com.globalss.dnb.monitor.security.LoadSalt</filter-class>
</filter>

<filter-mapping>
<filter-name>loadSalt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

为了在执行安全交易之前验证盐,我编写了另一个过滤器:

public class ValidateSalt implements Filter {

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

// Assume its HTTP
HttpServletRequest httpReq = (HttpServletRequest) request;

//String salt = (String) httpReq.getSession().getAttribute("csrfPreventionSalt");
String salt =(String) httpReq.getAttribute("csrfPreventionSalt");
System.out.println("I am in ValidateSalt : salt: "+salt);

// 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.");
}

}

public void init(FilterConfig arg0) throws ServletException {

}
public void destroy() {

}

}

web.xml 中第二个 Filetr 的映射

<filter>
<filter-name>validateSalt</filter-name>
<filter-class>com.globalss.dnb.monitor.security.ValidateSalt</filter-class>
</filter>

<filter-mapping>
<filter-name>validateSalt</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

在配置完这两个 servlet 之后,您所有的安全请求都失败了 :)。为了解决这个问题,我必须向以安全 URL 结尾的每个链接和表单帖子添加 csrfPreventionSalt 参数,其中包含具有相同名称的请求参数的值。例如,在 JSP 页面中的 HTML 表单中:

<form action="/transferMoneyServlet" method="get">
<input type="hidden" name="csrfPreventionSalt" value="<c:out value='${csrfPreventionSalt}'/>"/>
...
</form>

完成所有这些后,我尝试尝试 CSRF,这就是我所做的

<html>
<body>
<form action="http://localhost:8080/mywebapp/dispatcherServlet/addUserController/addUser" method="POST" enctype="text/plain">
<input type="hidden" name="&#123;&quot;userName&quot;&#58;&quot;CSRUser&quot;&#44;&quot;password&quot;&#58;&quot;CSRFUser123&quot;&#44;&quot;roles&quot;&#58;&quot;true&quot;&#44;&quot;status&quot;&#58;&quot;true&quot;&#125;" value="" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>

当我点击提交请求按钮时,我得到了成功响应,并在我的数据库中添加了 CSRUser。

我是否遗漏了什么,如何防止 CSRF 攻击?

最佳答案

您可以使用 Spring Security用于用户身份验证和授权。有 Cross Site Request Forgery (CSRF) Spring 3.2.0版本开始默认支持。

您还可以使用 RequestMatcher 轻松排除不想保护的 URL:

public class CsrfSecurityRequestMatcher implements RequestMatcher {
private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("/unprotected", null);

@Override
public boolean matches(HttpServletRequest request) {
if(allowedMethods.matcher(request.getMethod()).matches()){
return false;
}

return !unprotectedMatcher.matches(request);
}
}

Source

关于java - 如何防止我的网络应用程序在 Java 中受到 CSRF(跨站点请求伪造),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37726903/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com