Struts2 Xss 攻击预防的处理

摘要: 关于XSS问题的处理,此前在博客 http://blog.csdn.net/catoop/article/details/50338259 中写过处理方法。刚好最近朋友有问到“在Struts2中按文章中那样处理无效”,后来验证了下发现,Struts2 对请求的二次封装有所不同,于是针对Struts.

关于XSS问题的处理,此前在博客 http://blog.csdn.net/catoop/article/details/50338259 中写过处理方法。刚好最近朋友有问到“在Struts2中按文章中那样处理无效”,后来验证了下发现,Struts2 对请求的二次封装有所不同,于是针对Struts2如何处理XSS问题,按照本文的方法可以解决。

其主要思路就是,重写了StrutsPrepareAndExecuteFilter过滤器。

正常情况下我们在web.xml 中配置StrutsPrepareAndExecuteFilter的代码为:

  1. …………
  2. <filter>
  3. <filter-name>struts2</filter-name>
  4. <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  5. </filter>
  6. …………

将文章后面的几个类保存到项目中后,修改web.xml 的配置,指定我们新的MStrutsPrepareAndExecuteFilter类,代码如下:

  1. …………
  2. <filter>
  3. <filter-name>struts2</filter-name>
  4. <filter-class>cn.gx.wedding.common.struts2.MStrutsPrepareAndExecuteFilter</filter-class>
  5. </filter>
  6. …………

下面是相关的4个类源码(直接下载附件也行)
MDispatcher.java
MMultiPartRequestWrapper.java
MStrutsPrepareAndExecuteFilter.java
MStrutsRequestWrapper.java

这里说明下,因为struts2的源码中这4个类存在紧密的依赖耦合,所以只能把这4个类都重写出来,实际上其中并没有修改什么(详见MMultiPartRequestWrapper.java 和 MStrutsRequestWrapper.java)。

  1. package cn.gx.wedding.common.struts2;
  2. import java.util.Enumeration;
  3. import javax.servlet.http.HttpServletRequest;
  4. import org.apache.struts2.dispatcher.StrutsRequestWrapper;
  5. import cn.gx.wedding.util.XssShieldUtil;
  6. public class MStrutsRequestWrapper extends StrutsRequestWrapper {
  7. public MStrutsRequestWrapper(HttpServletRequest req) {
  8. super(req);
  9. }
  10. public MStrutsRequestWrapper(HttpServletRequest req, boolean bool) {
  11. super(req, bool);
  12. }
  13. @Override
  14. public String getParameter(String name) {
  15. name = XssShieldUtil.stripXss(name);
  16. // 返回值之前 先进行过滤
  17. return XssShieldUtil.stripXss(super.getParameter(name));
  18. }
  19. @Override
  20. public String[] getParameterValues(String name) {
  21. name = XssShieldUtil.stripXss(name);
  22. // 返回值之前 先进行过滤
  23. String[] values = super.getParameterValues(name);
  24. if(values != null){
  25. for (int i = 0; i < values.length; i++) {
  26. values[i] = XssShieldUtil.stripXss(values[i]);
  27. }
  28. }
  29. return values;
  30. }
  31. @Override
  32. public Enumeration<String> getParameterNames() {
  33. // Enumeration<String> names = super.getParameterNames();
  34. // while(names.hasMoreElements()){
  35. // String name = names.nextElement();
  36. // name = XssShieldUtil.stripXss(name);
  37. // }
  38. // return names;
  39. return super.getParameterNames();
  40. }
  41. }
  1. package cn.gx.wedding.common.struts2;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.util.Map;
  5. import javax.servlet.ServletContext;
  6. import javax.servlet.http.HttpServletRequest;
  7. import org.apache.struts2.StrutsConstants;
  8. import org.apache.struts2.dispatcher.Dispatcher;
  9. import org.apache.struts2.dispatcher.StrutsRequestWrapper;
  10. import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
  11. import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
  12. import com.opensymphony.xwork2.LocaleProvider;
  13. import com.opensymphony.xwork2.inject.Inject;
  14. import com.opensymphony.xwork2.util.logging.Logger;
  15. import com.opensymphony.xwork2.util.logging.LoggerFactory;
  16. public class MDispatcher extends Dispatcher {
  17. /**
  18. * Provide a logging instance.
  19. */
  20. private static final Logger LOG = LoggerFactory.getLogger(MDispatcher.class);
  21. /**
  22. * Store state of StrutsConstants.DISABLE_REQUEST_ATTRIBUTE_VALUE_STACK_LOOKUP setting.
  23. */
  24. private boolean disableRequestAttributeValueStackLookup;
  25. private ServletContext servletContext;
  26. private Map<String, String> initParams;
  27. private String multipartSaveDir;
  28. /**
  29. * Store state of StrutsConstants.STRUTS_DEVMODE setting.
  30. */
  31. private boolean devMode;
  32. public MDispatcher(ServletContext servletContext, Map<String, String> initParams) {
  33. super(servletContext, initParams);
  34. this.servletContext = servletContext;
  35. this.initParams = initParams;
  36. }
  37. @Override
  38. public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext)
  39. throws IOException {
  40. // don't wrap more than once
  41. if (request instanceof StrutsRequestWrapper) {
  42. return request;
  43. }
  44. String content_type = request.getContentType();
  45. if (content_type != null && content_type.contains("multipart/form-data")) {
  46. MultiPartRequest mpr = getMultiPartRequest();
  47. LocaleProvider provider = getContainer().getInstance(LocaleProvider.class);
  48. request = new MMultiPartRequestWrapper(mpr, request, getSaveDir(servletContext), provider);
  49. } else {
  50. request = new MStrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);
  51. }
  52. return request;
  53. }
  54. private String getSaveDir(ServletContext servletContext) {
  55. String saveDir = multipartSaveDir.trim();
  56. if (saveDir.equals("")) {
  57. File tempdir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
  58. if (LOG.isInfoEnabled()) {
  59. LOG.info("Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir");
  60. }
  61. if (tempdir != null) {
  62. saveDir = tempdir.toString();
  63. setMultipartSaveDir(saveDir);
  64. }
  65. } else {
  66. File multipartSaveDir = new File(saveDir);
  67. if (!multipartSaveDir.exists()) {
  68. if (!multipartSaveDir.mkdirs()) {
  69. String logMessage;
  70. try {
  71. logMessage = "Could not find create multipart save directory '" + multipartSaveDir.getCanonicalPath() + "'.";
  72. } catch (IOException e) {
  73. logMessage = "Could not find create multipart save directory '" + multipartSaveDir.toString() + "'.";
  74. }
  75. if (devMode) {
  76. LOG.error(logMessage);
  77. } else {
  78. if (LOG.isWarnEnabled()) {
  79. LOG.warn(logMessage);
  80. }
  81. }
  82. }
  83. }
  84. }
  85. if (LOG.isDebugEnabled()) {
  86. LOG.debug("saveDir=" + saveDir);
  87. }
  88. return saveDir;
  89. }
  90. /**
  91. * Modify state of StrutsConstants.STRUTS_MULTIPART_SAVEDIR setting.
  92. * @param val New setting
  93. */
  94. @Override
  95. @Inject(StrutsConstants.STRUTS_MULTIPART_SAVEDIR)
  96. public void setMultipartSaveDir(String val) {
  97. multipartSaveDir = val;
  98. }
  99. /**
  100. * Modify state of StrutsConstants.STRUTS_DEVMODE setting.
  101. * @param mode New setting
  102. */
  103. @Override
  104. @Inject(StrutsConstants.STRUTS_DEVMODE)
  105. public void setDevMode(String mode) {
  106. devMode = "true".equals(mode);
  107. }
  108. }
  1. package cn.gx.wedding.common.struts2;
  2. import java.util.Enumeration;
  3. import javax.servlet.http.HttpServletRequest;
  4. import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
  5. import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
  6. import cn.gx.wedding.util.XssShieldUtil;
  7. import com.opensymphony.xwork2.LocaleProvider;
  8. public class MMultiPartRequestWrapper extends MultiPartRequestWrapper {
  9. public MMultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir,
  10. LocaleProvider provider) {
  11. super(multiPartRequest, request, saveDir, provider);
  12. }
  13. @Override
  14. public String getParameter(String name) {
  15. name = XssShieldUtil.stripXss(name);
  16. // 返回值之前 先进行过滤
  17. return XssShieldUtil.stripXss(super.getParameter(name));
  18. }
  19. @Override
  20. public String[] getParameterValues(String name) {
  21. name = XssShieldUtil.stripXss(name);
  22. // 返回值之前 先进行过滤
  23. String[] values = super.getParameterValues(name);
  24. if(values != null){
  25. for (int i = 0; i < values.length; i++) {
  26. values[i] = XssShieldUtil.stripXss(values[i]);
  27. }
  28. }
  29. return values;
  30. }
  31. @Override
  32. public Enumeration<String> getParameterNames() {
  33. // Enumeration<String> names = super.getParameterNames();
  34. // while(names.hasMoreElements()){
  35. // String name = names.nextElement();
  36. // name = XssShieldUtil.stripXss(name);
  37. // }
  38. // return names;
  39. return super.getParameterNames();
  40. }
  41. }
  1. package cn.gx.wedding.common.struts2;
  2. import java.util.HashMap;
  3. import java.util.Iterator;
  4. import java.util.Map;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import org.apache.struts2.dispatcher.Dispatcher;
  8. import org.apache.struts2.dispatcher.ng.ExecuteOperations;
  9. import org.apache.struts2.dispatcher.ng.HostConfig;
  10. import org.apache.struts2.dispatcher.ng.InitOperations;
  11. import org.apache.struts2.dispatcher.ng.PrepareOperations;
  12. import org.apache.struts2.dispatcher.ng.filter.FilterHostConfig;
  13. import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
  14. public class MStrutsPrepareAndExecuteFilter extends StrutsPrepareAndExecuteFilter {
  15. @Override
  16. public void init(FilterConfig filterConfig) throws ServletException {
  17. InitOperations init = new InitOperations();
  18. Dispatcher dispatcher = null;
  19. try {
  20. FilterHostConfig config = new FilterHostConfig(filterConfig);
  21. init.initLogging(config);
  22. dispatcher = initDispatcher(config);
  23. init.initStaticContentLoader(config, dispatcher);
  24. prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
  25. execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
  26. this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
  27. postInit(dispatcher, filterConfig);
  28. } finally {
  29. if (dispatcher != null) {
  30. dispatcher.cleanUpAfterInit();
  31. }
  32. init.cleanup();
  33. }
  34. }
  35. /**
  36. * Creates and initializes the dispatcher
  37. */
  38. public Dispatcher initDispatcher(HostConfig filterConfig) {
  39. Dispatcher dispatcher = createDispatcher(filterConfig);
  40. dispatcher.init();
  41. return dispatcher;
  42. }
  43. /**
  44. * Create a {@link Dispatcher}
  45. */
  46. private Dispatcher createDispatcher(HostConfig filterConfig) {
  47. Map<String, String> params = new HashMap<String, String>();
  48. for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {
  49. String name = (String) e.next();
  50. String value = filterConfig.getInitParameter(name);
  51. params.put(name, value);
  52. }
  53. return new MDispatcher(filterConfig.getServletContext(), params);
  54. }
  55. }

如果使用的是springmvc、springboot等其他“非struts2”的框架,请参考 http://blog.csdn.net/catoop/article/details/50338259


原文地址:https://yq.aliyun.com/articles/7126#