在Web应用开发中,XSS(跨站脚本攻击)是一种常见且危险的安全漏洞。攻击者可以通过注入恶意脚本代码,在用户的浏览器中执行,从而窃取用户的敏感信息,如会话令牌、个人信息等。Struts2作为一个流行的Java Web应用框架,提供了一些关键技术点来防止XSS攻击,下面将详细介绍这些技术点。
输入验证与过滤
输入验证是防止XSS攻击的第一道防线。在Struts2中,我们可以通过自定义拦截器或者使用内置的验证机制来对用户输入进行验证和过滤。
自定义拦截器是一种灵活的方式,可以在请求处理之前对输入进行检查。以下是一个简单的自定义拦截器示例:
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class XSSInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof com.opensymphony.xwork2.ActionSupport) {
com.opensymphony.xwork2.ActionSupport actionSupport = (com.opensymphony.xwork2.ActionSupport) action;
// 获取所有请求参数
java.util.Map<String, Object> parameters = invocation.getInvocationContext().getParameters();
for (java.util.Map.Entry<String, Object> entry : parameters.entrySet()) {
if (entry.getValue() instanceof String[]) {
String[] values = (String[]) entry.getValue();
for (int i = 0; i < values.length; i++) {
values[i] = filterXSS(values[i]);
}
}
}
}
return invocation.invoke();
}
private String filterXSS(String input) {
if (input == null) {
return null;
}
// 简单的过滤,替换常见的恶意字符
input = input.replaceAll("<", "<").replaceAll(">", ">");
input = input.replaceAll("\"", """).replaceAll("'", "'");
input = input.replaceAll("\\(", "(").replaceAll("\\)", ")");
input = input.replaceAll("eval\\((.*)\\)", "");
input = input.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
return input;
}
}在struts.xml中配置该拦截器:
<interceptors>
<interceptor name="xssInterceptor" class="com.example.XSSInterceptor"/>
<interceptor-stack name="xssStack">
<interceptor-ref name="xssInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="xssStack"/>除了自定义拦截器,Struts2还提供了内置的验证框架。可以在Action类中使用注解或者配置文件来定义验证规则。例如,使用注解进行验证:
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator;
import com.opensymphony.xwork2.ActionSupport;
public class MyAction extends ActionSupport {
private String input;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
@RequiredStringValidator(message = "输入不能为空")
@StringLengthFieldValidator(minLength = "1", maxLength = "100", message = "输入长度必须在1到100之间")
public String execute() {
return SUCCESS;
}
}输出编码
即使对输入进行了验证和过滤,在输出时也需要进行编码,以防止攻击者通过构造特殊的输入绕过输入验证。Struts2提供了多种方式来进行输出编码。
在JSP页面中,可以使用Struts2的标签库来自动进行编码。例如,使用<s:property>标签:
<s:property value="input" escapeHtml="true"/>
这里的escapeHtml属性设置为true,表示对输出进行HTML编码。
如果需要在Java代码中进行输出编码,可以使用Apache Commons Lang库中的StringEscapeUtils类。例如:
import org.apache.commons.lang3.StringEscapeUtils;
public class OutputEncoder {
public static String encodeOutput(String input) {
return StringEscapeUtils.escapeHtml4(input);
}
}在Action类中使用该方法进行编码:
import com.opensymphony.xwork2.ActionSupport;
public class MyAction extends ActionSupport {
private String input;
public String getInput() {
return OutputEncoder.encodeOutput(input);
}
public void setInput(String input) {
this.input = input;
}
public String execute() {
return SUCCESS;
}
}HTTP头信息设置
合理设置HTTP头信息可以增强对XSS攻击的防护。Struts2可以通过拦截器或者过滤器来设置HTTP头信息。
例如,设置Content-Security-Policy(CSP)头信息,它可以限制页面可以加载的资源,从而防止恶意脚本的注入。以下是一个简单的过滤器示例:
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CSPFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (response instanceof HttpServletResponse) {
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 只允许从当前域名加载脚本和样式
httpResponse.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self'");
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}在web.xml中配置该过滤器:
<filter>
<filter-name>CSPFilter</filter-name>
<filter-class>com.example.CSPFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CSPFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>另外,还可以设置X-XSS-Protection头信息,它可以让浏览器启用内置的XSS防护机制。在Struts2的拦截器中设置该头信息:
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import javax.servlet.http.HttpServletResponse;
public class XSSProtectionInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().getServletResponse();
response.setHeader("X-XSS-Protection", "1; mode=block");
return invocation.invoke();
}
}在struts.xml中配置该拦截器:
<interceptors>
<interceptor name="xssProtectionInterceptor" class="com.example.XSSProtectionInterceptor"/>
<interceptor-stack name="xssProtectionStack">
<interceptor-ref name="xssProtectionInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="xssProtectionStack"/>使用安全的标签库和组件
Struts2提供了丰富的标签库和组件,使用这些安全的标签库和组件可以减少XSS攻击的风险。例如,使用Struts2的表单标签来生成表单,它会自动处理输入和输出的编码。
<s:form action="myAction">
<s:textfield name="input" label="输入"/>
<s:submit value="提交"/>
</s:form>这样可以确保用户输入和输出都经过了正确的处理,减少了XSS攻击的可能性。
综上所述,Struts2通过输入验证与过滤、输出编码、HTTP头信息设置以及使用安全的标签库和组件等关键技术点,可以有效地防止XSS攻击。在开发Struts2应用时,应该综合运用这些技术点,确保应用的安全性。