diff --git a/im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java b/im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java index 71561d2..32a3777 100644 --- a/im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java +++ b/im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java @@ -1,6 +1,7 @@ package com.bx.implatform.config; import com.bx.implatform.interceptor.AuthInterceptor; +import com.bx.implatform.interceptor.XssInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -15,18 +16,25 @@ public class MvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(XssInterceptor()) + .addPathPatterns("/**"); registry.addInterceptor(authInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/login","/logout","/register","/refreshToken", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**"); } - @Bean public AuthInterceptor authInterceptor() { return new AuthInterceptor(); } + @Bean + public XssInterceptor XssInterceptor() { + return new XssInterceptor(); + } + + @Bean public PasswordEncoder passwordEncoder(){ // 使用BCrypt加密密码 diff --git a/im-platform/src/main/java/com/bx/implatform/config/XssBodyConfig.java b/im-platform/src/main/java/com/bx/implatform/config/XssBodyConfig.java deleted file mode 100644 index bddec47..0000000 --- a/im-platform/src/main/java/com/bx/implatform/config/XssBodyConfig.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.bx.implatform.config; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import org.apache.commons.lang3.StringEscapeUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; - -import javax.annotation.PostConstruct; -import java.io.IOException; - -@Configuration -public class XssBodyConfig { - - @Autowired - private ObjectMapper objectMapper; - - @PostConstruct - public void afterPropertiesSet() throws Exception { - SimpleModule simpleModule = new SimpleModule(); - simpleModule.addDeserializer(String.class, new JsonHtmlXssDeserializer()); - objectMapper.registerModule(simpleModule); - } - - - class JsonHtmlXssDeserializer extends JsonDeserializer { - - @Override - public Class handledType() { - return String.class; - } - - @Override - public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { - String value = jsonParser.getValueAsString(); - if (StringUtils.isNotEmpty(value)) { - return StringEscapeUtils.escapeHtml4(value); - } - return value; - } - -} -} \ No newline at end of file diff --git a/im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java b/im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java index 74981f6..dc5cb40 100644 --- a/im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java +++ b/im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java @@ -14,6 +14,7 @@ public enum ResultCode { PROGRAM_ERROR(500,"系统繁忙,请稍后再试"), PASSWOR_ERROR(10001,"密码不正确"), USERNAME_ALREADY_REGISTER(10003,"该用户名已注册"), + XSS_PARAM_ERROR(10004,"请不要输入非法内容"), ; diff --git a/im-platform/src/main/java/com/bx/implatform/filter/XssFilter.java b/im-platform/src/main/java/com/bx/implatform/filter/CacheFilter.java similarity index 82% rename from im-platform/src/main/java/com/bx/implatform/filter/XssFilter.java rename to im-platform/src/main/java/com/bx/implatform/filter/CacheFilter.java index d47c627..9353e0f 100644 --- a/im-platform/src/main/java/com/bx/implatform/filter/XssFilter.java +++ b/im-platform/src/main/java/com/bx/implatform/filter/CacheFilter.java @@ -12,7 +12,7 @@ import java.util.List; @Component @ServletComponentScan @WebFilter(urlPatterns = "/*",filterName = "xssFilter") -public class XssFilter implements Filter { +public class CacheFilter implements Filter { @Override public void init(FilterConfig filterConfig) {} @@ -22,7 +22,7 @@ public class XssFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response); + chain.doFilter(new CacheHttpServletRequestWrapper((HttpServletRequest) request), response); } } \ No newline at end of file diff --git a/im-platform/src/main/java/com/bx/implatform/filter/CacheHttpServletRequestWrapper.java b/im-platform/src/main/java/com/bx/implatform/filter/CacheHttpServletRequestWrapper.java new file mode 100644 index 0000000..761c743 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/filter/CacheHttpServletRequestWrapper.java @@ -0,0 +1,61 @@ +package com.bx.implatform.filter; + +import org.apache.commons.compress.utils.IOUtils; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.*; + +public class CacheHttpServletRequestWrapper extends HttpServletRequestWrapper { + private byte[] requestBody; + private HttpServletRequest request; + + public CacheHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + this.request = request; + } + + + @Override + public ServletInputStream getInputStream() throws IOException { + if (null == this.requestBody) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IOUtils.copy(request.getInputStream(), baos); + this.requestBody = baos.toByteArray(); + } + ByteArrayInputStream bais = new ByteArrayInputStream(requestBody); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener listener) { + } + + @Override + public int read() { + return bais.read(); + } + }; + } + + public byte[] getRequestBody() { + return requestBody; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + +} diff --git a/im-platform/src/main/java/com/bx/implatform/filter/XssHttpServletRequestWrapper.java b/im-platform/src/main/java/com/bx/implatform/filter/XssHttpServletRequestWrapper.java deleted file mode 100644 index 36ac7d6..0000000 --- a/im-platform/src/main/java/com/bx/implatform/filter/XssHttpServletRequestWrapper.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.bx.implatform.filter; - -import cn.hutool.extra.servlet.ServletUtil; -import lombok.SneakyThrows; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.StringEscapeUtils; -import org.springframework.web.util.HtmlUtils; - -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; - -public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { - - public XssHttpServletRequestWrapper(HttpServletRequest request) { - super(request); - } - - @Override - public String getQueryString() { - return StringEscapeUtils.escapeHtml4(super.getQueryString()); - } - - @Override - public String getParameter(String name) { - return StringEscapeUtils.escapeHtml4(super.getParameter(name)); - } - - @Override - public String[] getParameterValues(String name) { - String[] values = super.getParameterValues(name); - if (ArrayUtils.isEmpty(values)) { - return values; - } - int length = values.length; - String[] escapeValues = new String[length]; - for (int i = 0; i < length; i++) { - escapeValues[i] = StringEscapeUtils.escapeHtml4(values[i]); - } - return escapeValues; - } -} diff --git a/im-platform/src/main/java/com/bx/implatform/interceptor/XssInterceptor.java b/im-platform/src/main/java/com/bx/implatform/interceptor/XssInterceptor.java new file mode 100644 index 0000000..fd384e1 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/interceptor/XssInterceptor.java @@ -0,0 +1,48 @@ +package com.bx.implatform.interceptor; + +import com.bx.implatform.enums.ResultCode; +import com.bx.implatform.exception.GlobalException; +import com.bx.implatform.util.XssUtil; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.util.Map; + +@Slf4j +public class XssInterceptor implements HandlerInterceptor { + + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // 检查参数 + Map paramMap = request.getParameterMap(); + for(String[] values:paramMap.values()){ + for(String value:values){ + if(XssUtil.checkXss(value)){ + throw new GlobalException(ResultCode.XSS_PARAM_ERROR); + } + } + } + // 检查body + String body = getBody(request); + if(XssUtil.checkXss(body)){ + throw new GlobalException(ResultCode.XSS_PARAM_ERROR); + } + return true; + } + + @SneakyThrows + private String getBody(HttpServletRequest request){ + BufferedReader reader = request.getReader(); + StringBuilder stringBuilder = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + return stringBuilder.toString(); + } +} diff --git a/im-platform/src/main/java/com/bx/implatform/util/XssUtil.java b/im-platform/src/main/java/com/bx/implatform/util/XssUtil.java new file mode 100644 index 0000000..15461a3 --- /dev/null +++ b/im-platform/src/main/java/com/bx/implatform/util/XssUtil.java @@ -0,0 +1,20 @@ +package com.bx.implatform.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class XssUtil { + + private static final String XSS_PATTERN = "((?i))|((?i)alert\\s*\\()|((?i)prompt\\s*\\()|((?i)document\\.cookie)|((?i)location\\.href)|((?i)window\\.location)|((?i)onerror\\s*\\()|((?i)eval\\s*\\()|((?i)window\\.open\\s*\\()|((?i)innerHTML)|((?i)onclick\\s*\\()|((?i)onmouseover\\s*\\()|((?i)onsubmit\\s*\\()|((?i)onload\\s*\\()|((?i)onfocus\\s*\\()|((?i)onblur\\s*\\()|((?i)onkeyup\\s*\\()|((?i)onkeydown\\s*\\()|((?i)onkeypress\\s*\\()|((?i)onmouseout\\s*\\()|((?i)src=)|((?i)href=)|((?i)style=)|((?i)background=)|((?i)expression\\s*\\()|((?i)XMLHttpRequest\\s*\\()|((?i)ActiveXObject\\s*\\()|((?i)iframe)|((?i)document\\.write\\s*\\()|((?i)document\\.writeln\\s*\\()|((?i)setTimeout\\s*\\()|((?i)setInterval\\s*\\()|((?i)onreadystatechange\\s*\\()|((?i)appendChild\\s*\\()|((?i)createTextNode\\s*\\()|((?i)createElement\\s*\\()|((?i)getElementsByTagName\\s*\\()|((?i)getElementsByClassName\\s*\\()|((?i)querySelector\\s*\\()|((?i)querySelectorAll\\s*\\()|((?i)document\\.location)|((?i)document\\.body\\.innerHTML)|((?i)document\\.forms)|((?i)document\\.images)|((?i)document\\.links)|((?i)document\\.URL)|((?i)document\\.domain)|((?i)document\\.referrer)|((?i)history\\.back\\s*\\()"; + private static final Pattern PATTERN = Pattern.compile(XSS_PATTERN); + + public static boolean checkXss(String inputString) { + if (inputString!=null) { + Matcher matcher = PATTERN.matcher(inputString); + if (matcher.find()) { + return true; + } + } + return false; + } +}