Skip to content

Commit

Permalink
解决@PathVariable的xss攻击问题
Browse files Browse the repository at this point in the history
  • Loading branch information
zhou committed Jun 14, 2015
1 parent a285596 commit d05690c
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 67 deletions.
65 changes: 21 additions & 44 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
<artifactId>spring-webmvc</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.5.RELEASE</version>
<scope>test</scope>
</dependency>

<!-- jsoup -->
<dependency>
Expand Down Expand Up @@ -229,34 +235,6 @@

</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<versionRange>[2.0,)</versionRange>
<goals>
<goal>copy-dependencies</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore />
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
Expand All @@ -272,25 +250,24 @@
<configuration>
<version>3.0</version>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>zblog</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>src/main/webapp/WEB-INF/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- 以mvn jetty:run运行 -->
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.6.v20141205</version>
<configuration>
<httpConnector>
<port>9080</port>
</httpConnector>
<scanIntervalSeconds>20</scanIntervalSeconds>
<webApp>
<contextPath>/</contextPath>
</webApp>
</configuration>
</plugin>
</plugins>
</build>
</project>
7 changes: 2 additions & 5 deletions src/main/java/com/zblog/biz/editor/Ueditor.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import java.util.Arrays;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Component;
Expand All @@ -29,8 +27,7 @@ public class Ueditor{
@Autowired
private UploadManager uploadManager;

public MapContainer server(HttpServletRequest request){
ServletRequestReader reader = new ServletRequestReader(request);
public MapContainer server(ServletRequestReader reader){
String action = reader.getAsString("action");

MapContainer result = null;
Expand Down Expand Up @@ -90,7 +87,7 @@ public MapContainer uploadImage(ServletRequestReader reader){
e.printStackTrace();
upload = null;
}

if(upload == null){
return new MapContainer("state", "文件上传失败");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import java.io.InputStream;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -22,6 +20,7 @@
import com.zblog.biz.editor.Ueditor;
import com.zblog.core.dal.entity.Upload;
import com.zblog.core.plugin.MapContainer;
import com.zblog.core.util.web.ServletRequestReader;
import com.zblog.core.util.web.WebContextFactory;

@Controller
Expand Down Expand Up @@ -67,8 +66,8 @@ public Object remove(@PathVariable("uploadid") String uploadid){

@ResponseBody
@RequestMapping(value = "/ueditor")
public Object ueditor(HttpServletRequest request){
return ueditor.server(request);
public Object ueditor(ServletRequestReader reader){
return ueditor.server(reader);
}

}
26 changes: 16 additions & 10 deletions src/main/java/com/zblog/web/front/controller/ArchiveController.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.zblog.web.front.controller;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
Expand All @@ -21,19 +26,20 @@ public class ArchiveController{
private PostManager postManager;

@RequestMapping(value = "/{yearMonth}", method = RequestMethod.GET)
public String post(@PathVariable("yearMonth") int yearMonth,
public String post(@PathVariable("yearMonth") Date yearMonth,
@RequestParam(value = "page", defaultValue = "1") int page, Model model){
Date date = DateUtils.parse("yyyyMM", yearMonth + "");
String result = "404";
if(date != null){
model.addAttribute("page", postManager.listByMonth(date, page, 10));
model.addAttribute(WebConstants.PRE_TITLE_KEY, DateUtils.formatDate("MMM,yyyy", date));
model.addAttribute("page", postManager.listByMonth(yearMonth, page, 10));
model.addAttribute(WebConstants.PRE_TITLE_KEY, DateUtils.formatDate("MMM,yyyy", yearMonth));

model.addAttribute("archive", date);
result = "index";
}
model.addAttribute("archive", yearMonth);
return "index";
}

return result;
@InitBinder
public void initBinder(WebDataBinder binder){
DateFormat format = new SimpleDateFormat("yyyyMM");
format.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(format, false));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class TagController{
public String post(@PathVariable("tagName") String tagName,
@RequestParam(value = "page", defaultValue = "1") int page, Model model){
model.addAttribute("page", postManager.listByTag(tagName, page, 10));

model.addAttribute("tag", tagName);
model.addAttribute(WebConstants.PRE_TITLE_KEY, tagName);
return "index";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.zblog.web.resovler;

import javax.servlet.http.HttpServletRequest;

import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.zblog.core.util.web.ServletRequestReader;

public class ServletRequestReaderArgumentsResolver implements HandlerMethodArgumentResolver{

@Override
public boolean supportsParameter(MethodParameter parameter){
return parameter.getParameterType() == ServletRequestReader.class;
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception{
return new ServletRequestReader(webRequest.getNativeRequest(HttpServletRequest.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.zblog.web.resovler;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.MultiValueMap;
import org.springframework.web.servlet.handler.AbstractHandlerMapping;
import org.springframework.web.util.HtmlUtils;
import org.springframework.web.util.UrlPathHelper;

import com.zblog.core.util.CollectionUtils;

/**
* 解决@PathVariable注解造成的xss攻击问题,注意:此类必需由WebApplicationContext初始化
*
* @author zhou
*
*/
public class XssHandlerMappingPostProcessor implements BeanPostProcessor{

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException{
return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException{
if(bean instanceof AbstractHandlerMapping){
AbstractHandlerMapping ahm = (AbstractHandlerMapping) bean;
ahm.setUrlPathHelper(new XssUrlPathHelper());
}

return bean;
}

static class XssUrlPathHelper extends UrlPathHelper{

@Override
public Map<String, String> decodePathVariables(HttpServletRequest request, Map<String, String> vars){
Map<String, String> result = super.decodePathVariables(request, vars);
if(!CollectionUtils.isEmpty(result)){
for(String key : result.keySet()){
result.put(key, cleanXSS(result.get(key)));
}
}

return result;
}

@Override
public MultiValueMap<String, String> decodeMatrixVariables(HttpServletRequest request,
MultiValueMap<String, String> vars){
MultiValueMap<String, String> mvm = super.decodeMatrixVariables(request, vars);
if(!CollectionUtils.isEmpty(mvm)){
for(String key : mvm.keySet()){
List<String> value = mvm.get(key);
for(int i = 0; i < value.size(); i++){
value.set(i, cleanXSS(value.get(i)));
}
}
}

return mvm;
}

private String cleanXSS(String value){
return HtmlUtils.htmlEscape(value);
}

}

}
12 changes: 9 additions & 3 deletions src/main/resources/config/spring-servlet.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

<mvc:annotation-driven>
<mvc:annotation-driven enableMatrixVariables="false">
<mvc:message-converters register-defaults="true">
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
Expand All @@ -20,17 +20,23 @@
</property>
</bean>
</mvc:message-converters>
<mvc:argument-resolvers>
<!-- controller中可以直接使用ServletRequestReader类 -->
<bean class="com.zblog.web.resovler.ServletRequestReaderArgumentsResolver" />
</mvc:argument-resolvers>
<!-- 可不设置,使用默认的超时时间,当前为5分钟 -->
<mvc:async-support default-timeout="300000" />
</mvc:annotation-driven>

<context:component-scan base-package="com.zblog.web.front.controller" />
<context:component-scan base-package="com.zblog.web.backend.controller" />

<mvc:resources mapping="/resource/**" location="/resource/" />
<mvc:resources mapping="/post/**" location="/post/" />
<bean class="com.zblog.web.resovler.XssHandlerMappingPostProcessor" />

<!-- 定义无需Controller的url<->view直接映射
<mvc:resources mapping="/resource/**" location="/resource/" />
<mvc:resources mapping="/post/**" location="/post/" />
<mvc:view-controller path="/backend" view-name="/backend/login" />
-->

Expand Down
4 changes: 4 additions & 0 deletions src/main/webapp/WEB-INF/web.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@
<servlet-name>default</servlet-name>
<url-pattern>/resource/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/post/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>Zblog</servlet-name>
Expand Down

0 comments on commit d05690c

Please sign in to comment.