如何在Struts2应用程序中为AJAX请求实现CSRF保护。

7 浏览
0 Comments

如何在Struts2应用程序中为AJAX请求实现CSRF保护。

我有一个基于Struts2的Web应用程序,我需要实现CSRF保护。对于静态表单来说,这是非常简单的。我只需要激活tokenSession拦截器,然后在要提交的表单中设置(在这里有解释:这里这里)。

但是,当我需要为不一定通过表单提交的POST AJAX调用(我正在使用jQuery)启用CSRF保护时,问题就出现了。在进行后续的AJAX调用时,我遇到了重用令牌的问题。

如果有任何指导或不同的方法,我将不胜感激。

0
0 Comments

问题的原因是在Struts2应用程序中,对于AJAX请求缺乏跨站请求伪造(CSRF)保护。作者通过为AJAX请求生成令牌,并将其与正常响应一起发送来解决这个问题。他计划将此过程抽象为一个实用方法,对于需要重复执行而无需刷新页面的操作,将该方法作为响应的一部分返回。作者仍在寻找一个更优雅的解决方案。

以下是作者提供的代码示例:

    Map<String, String> tokenInfo = Maps.newHashMap();
    tokenInfo.put("struts.token.name", TokenHelper.getTokenName());
    tokenInfo.put(TokenHelper.getTokenName(), TokenHelper.setToken());

作者还表示他们也遇到了这个问题,并询问是否有更好的解决方案。同时,他们还询问作者的解决方案是否对JSP文件进行了任何更改。

0
0 Comments

问题的原因是需要在Struts2应用程序中为AJAX请求实现CSRF保护,并且还需要防止重复提交。

解决方法是生成一个令牌,并将其作为参数在ajax调用中使用。对于后续的AJAX调用,可以使用一个“每个用户”的令牌,不一定是“每个请求”的令牌。这在Stack Overflow的一个答案中有解释。然而,这种方法对于防止重复提交并不是非常有效。

以下是一种可能的解决方案:

public class CsrfInterceptor extends AbstractInterceptor {
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        
        // Check if it's an AJAX request
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            String token = (String) request.getSession().getAttribute("csrfToken");
            String requestToken = request.getParameter("csrfToken");
            // Check if the token matches
            if (token == null || !token.equals(requestToken)) {
                response.sendError(HttpServletResponse.SC_FORBIDDEN, "CSRF token validation failed");
                return null;
            }
        }
        
        // Continue with the action
        return invocation.invoke();
    }
}

在Struts2配置文件中,将此拦截器添加到适当的位置:


    
    
        
        
    


在首次加载页面时,生成一个CSRF令牌,并将其存储在会话中:

public class MyAction extends ActionSupport {
    @Override
    public String execute() throws Exception {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpSession session = request.getSession();
        
        // Generate a CSRF token
        String token = UUID.randomUUID().toString();
        
        // Store the token in the session
        session.setAttribute("csrfToken", token);
        
        return SUCCESS;
    }
}

在AJAX请求中,将令牌作为参数发送:

var csrfToken = "${sessionScope.csrfToken}";
$.ajax({
    url: "ajaxUrl",
    type: "POST",
    data: {
        csrfToken: csrfToken,
        // Other parameters
    },
    success: function(response) {
        // Handle success
    },
    error: function(xhr, status, error) {
        // Handle error
    }
});

这样,每次发起AJAX请求时,都会检查令牌是否匹配。如果令牌不匹配,将返回403 Forbidden错误。这样可以防止CSRF攻击,并且还可以防止重复提交。

0