• Struts 2 防御存储型XSS攻击


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

    创建XSS拦截器

    1. 创建一个XSS拦截器类,实现com.opensymphony.xwork2.interceptor.Interceptor接口。
      1. import com.hoau.hbdp.framework.define.Protocol;
      2. import com.hoau.hbdp.framework.server.context.AppContext;
      3. import com.hoau.hbdp.framework.server.web.interceptor.AbstractInterceptor;
      4. import com.hoau.hbdp.framework.server.web.result.json.JSONPopulator;
      5. import com.hoau.hbdp.framework.server.web.result.json.annotation.JSON;
      6. import com.hoau.hbdp.framework.server.web.xss.ParametersValidatorException;
      7. import com.opensymphony.xwork2.ActionInvocation;
      8. import org.apache.commons.logging.Log;
      9. import org.apache.commons.logging.LogFactory;
      10. import org.apache.struts2.ServletActionContext;
      11. import org.codehaus.jackson.map.ObjectMapper;
      12. import org.springframework.core.annotation.AnnotationUtils;
      13. import org.springframework.util.ReflectionUtils;
      14. import javax.servlet.http.HttpServletRequest;
      15. import javax.servlet.http.HttpServletResponse;
      16. import java.io.BufferedReader;
      17. import java.lang.reflect.Method;
      18. import java.util.Map;
      19. import java.util.regex.Pattern;
      20. /**
      21. * @author
      22. * @desc 防存储箱Xss攻击
      23. * @date 2023/11/06 10:43
      24. **/
      25. public class XssInterceptor extends AbstractInterceptor {
      26. private static final long serialVersionUID = -3423290391156261612L;
      27. private final Log log = LogFactory.getLog(getClass());
      28. /**
      29. * 序列化及缓存类
      30. */
      31. private static final ObjectMapper MAPPER = new ObjectMapper();
      32. /**
      33. * JSON格式反序列化并绑定到Action中的属性上
      34. *
      35. * @param invocation
      36. * @return
      37. * @throws Exception
      38. * @since:
      39. * @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(ActionInvocation)
      40. * intercept
      41. */
      42. @Override
      43. public String intercept(ActionInvocation invocation) throws Exception {
      44. HttpServletRequest request = ServletActionContext.getRequest();
      45. HttpServletResponse response = ServletActionContext.getResponse();
      46. String contentType = request.getHeader("content-type");
      47. if (contentType != null) {
      48. int iSemicolonIdx = contentType.indexOf(';');
      49. if (iSemicolonIdx != -1) {
      50. contentType = contentType.substring(0, iSemicolonIdx);
      51. }
      52. }
      53. Object rootObject = invocation.getAction();
      54. Class clazz = invocation.getAction().getClass();
      55. String methodName = invocation.getProxy().getMethod();
      56. Method method = ReflectionUtils.findMethod(clazz, methodName);
      57. //如果在Action方法上加入JSON的注解,那么就可以在应用这个方法的时候,把错误的结果信息转换为json
      58. if (Protocol.JSON_CONTENT_TYPE.equalsIgnoreCase(contentType) || AnnotationUtils.isAnnotationDeclaredLocally(JSON.class, clazz)
      59. || (method != null && method.isAnnotationPresent(JSON.class))) {
      60. BufferedReader reader = request.getReader();
      61. int bytesRead;
      62. StringBuilder stringBuilder = new StringBuilder();
      63. char[] charBuffer = new char[2048];
      64. while ((bytesRead = reader.read(charBuffer)) > 0) {
      65. stringBuilder.append(charBuffer, 0, bytesRead);
      66. }
      67. if (stringBuilder.toString().length() > 0) {
      68. //过滤参数
      69. try {
      70. String valuestr = AppContext.getParametersValidator().doValidator(stringBuilder.toString(), response);
      71. valuestr = stripXSS(valuestr);
      72. @SuppressWarnings("rawtypes")
      73. Map json = MAPPER.readValue(valuestr, Map.class);
      74. JSONPopulator.populateObject(rootObject, json);
      75. } catch (ParametersValidatorException e) {
      76. return "success";
      77. }
      78. }
      79. } else {
      80. if (log.isDebugEnabled()) {
      81. log.debug("Content type must be 'application/json' or 'application/json-rpc'. Ignoring request with content type "
      82. + contentType);
      83. }
      84. }
      85. return invocation.invoke();
      86. }
      87. private String stripXSS(String value) {
      88. if (value != null) {
      89. value = value.replaceAll("", "");
      90. Pattern scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE);
      91. value = scriptPattern.matcher(value).replaceAll("");
      92. // Avoid anything in a src='...' type of expression
      93. scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      94. value = scriptPattern.matcher(value).replaceAll("");
      95. scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      96. value = scriptPattern.matcher(value).replaceAll("");
      97. scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
      98. value = scriptPattern.matcher(value).replaceAll("");
      99. // Remove any lonesome tag
      100. scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE);
      101. value = scriptPattern.matcher(value).replaceAll("");
      102. // Remove any lonesome