Struts 2 防御存储型XSS攻击

本文介绍了如何在Struts框架中通过创建自定义拦截器来防止XSS攻击,包括XSSInterceptor类的实现和在struts.xml配置文件中的应用,以及注意事项。
摘要由CSDN通过智能技术生成

在Struts中拦截XSS攻击可以通过配置拦截器来实现。以下是一个示例代码来演示如何在Struts中拦截XSS攻击:

创建XSS拦截器类

  1. 创建一个XSS拦截器类,实现com.opensymphony.xwork2.interceptor.Interceptor接口。
    import com.hoau.hbdp.framework.define.Protocol;
    import com.hoau.hbdp.framework.server.context.AppContext;
    import com.hoau.hbdp.framework.server.web.interceptor.AbstractInterceptor;
    import com.hoau.hbdp.framework.server.web.result.json.JSONPopulator;
    import com.hoau.hbdp.framework.server.web.result.json.annotation.JSON;
    import com.hoau.hbdp.framework.server.web.xss.ParametersValidatorException;
    import com.opensymphony.xwork2.ActionInvocation;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.struts2.ServletActionContext;
    import org.codehaus.jackson.map.ObjectMapper;
    import org.springframework.core.annotation.AnnotationUtils;
    import org.springframework.util.ReflectionUtils;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedReader;
    import java.lang.reflect.Method;
    import java.util.Map;
    import java.util.regex.Pattern;
    
    /**
     * @author 
     * @desc 防存储箱Xss攻击
     * @date 2023/11/06 10:43
     **/
    public class XssInterceptor extends AbstractInterceptor {
    
        private static final long serialVersionUID = -3423290391156261612L;
    
        private final Log log = LogFactory.getLog(getClass());
    
        /**
         * 序列化及缓存类
         */
        private static final ObjectMapper MAPPER = new ObjectMapper();
    
    
        /**
         * JSON格式反序列化并绑定到Action中的属性上
         *
         * @param invocation
         * @return
         * @throws Exception
         * @since:
         * @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(ActionInvocation)
         * intercept
         */
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            HttpServletRequest request = ServletActionContext.getRequest();
            HttpServletResponse response = ServletActionContext.getResponse();
            String contentType = request.getHeader("content-type");
            if (contentType != null) {
                int iSemicolonIdx = contentType.indexOf(';');
                if (iSemicolonIdx != -1) {
                    contentType = contentType.substring(0, iSemicolonIdx);
                }
            }
    
            Object rootObject = invocation.getAction();
    
            Class<?> clazz = invocation.getAction().getClass();
            String methodName = invocation.getProxy().getMethod();
            Method method = ReflectionUtils.findMethod(clazz, methodName);
            //如果在Action方法上加入JSON的注解,那么就可以在应用这个方法的时候,把错误的结果信息转换为json
            if (Protocol.JSON_CONTENT_TYPE.equalsIgnoreCase(contentType) || AnnotationUtils.isAnnotationDeclaredLocally(JSON.class, clazz)
                    || (method != null && method.isAnnotationPresent(JSON.class))) {
                BufferedReader reader = request.getReader();
                int bytesRead;
                StringBuilder stringBuilder = new StringBuilder();
                char[] charBuffer = new char[2048];
                while ((bytesRead = reader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
                if (stringBuilder.toString().length() > 0) {
                    //过滤参数
                    try {
                        String valuestr = AppContext.getParametersValidator().doValidator(stringBuilder.toString(), response);
                        valuestr = stripXSS(valuestr);
                        @SuppressWarnings("rawtypes")
                        Map json = MAPPER.readValue(valuestr, Map.class);
                        JSONPopulator.populateObject(rootObject, json);
                    } catch (ParametersValidatorException e) {
                        return "success";
                    }
                }
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("Content type must be 'application/json' or 'application/json-rpc'. Ignoring request with content type "
                            + contentType);
                }
            }
            return invocation.invoke();
        }
    
        private String stripXSS(String value) {
            if (value != null) {
                value = value.replaceAll("", "");
                Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Avoid anything in a src='...' type of expression
                scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Remove any lonesome </script> tag
                scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Remove any lonesome <script ...> tag
                scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Avoid eval(...) expressions
                scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Avoid expression(...) expressions
                scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Avoid javascript:... expressions
                scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Avoid vbscript:... expressions
                scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
    
                // Avoid onload= expressions
                scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                scriptPattern = Pattern.compile("onerror(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
    
                value = value.replaceAll(">", "〉").replaceAll("<", "〈");
            }
            return value;
        }
    
        @Override
        public void init() {
            super.init();
        }
    
    }

    在上述代码中,我们使用AbstractInterceptor作为基类,实现了intercept方法,该方法会在请求被处理之前拦截并进行XSS过滤。我们获取请求的参数,并对每个参数的值进行sanitize方法的调用,该方法用于执行XSS过滤逻辑。

配置文件

在Struts的配置文件(如struts.xml)中配置拦截器。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

<package name="struts-default" extends="framework-default">
<interceptors>
<interceptor name="json" class="com.example.framework.server.web.interceptor.JSONInterceptor"/>
    <interceptor name="xssInterceptor" class="com.example.XSSInterceptor" />
    <interceptor-stack name="xssInterceptorStack">
        <interceptor-ref name="xssInterceptor" />
        <interceptor-ref name="json" />
    </interceptor-stack>
</interceptors>

</package>

</struts>

注意点

在 struts.xml中  <interceptor-ref name="xssInterceptor" /> 前面不能配置拦截参数,不然就会一直获取不到参数,如我之前 <interceptor-ref name="json" /> 在前面导致一直XSSInterceptor拦截器中一直获取不到参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值