mirror of
https://github.com/chillzhuang/blade-tool
synced 2024-12-12 12:19:27 +08:00
⚡ 优化Xss运行逻辑
This commit is contained in:
parent
edc1f5d138
commit
c42b165f27
@ -16,10 +16,9 @@
|
|||||||
package org.springblade.core.tool.config;
|
package org.springblade.core.tool.config;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springblade.core.tool.support.xss.XssFilter;
|
import org.springblade.core.tool.request.BladeRequestFilter;
|
||||||
import org.springblade.core.tool.support.xss.XssProperties;
|
import org.springblade.core.tool.request.RequestProperties;
|
||||||
import org.springblade.core.tool.support.xss.XssUrlProperties;
|
import org.springblade.core.tool.request.XssProperties;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
@ -29,31 +28,28 @@ import org.springframework.core.Ordered;
|
|||||||
import javax.servlet.DispatcherType;
|
import javax.servlet.DispatcherType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Xss配置类
|
* 过滤器配置类
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ConditionalOnProperty(value = "blade.xss.enabled", havingValue = "true")
|
@EnableConfigurationProperties({RequestProperties.class, XssProperties.class})
|
||||||
@EnableConfigurationProperties({XssProperties.class, XssUrlProperties.class})
|
public class RequestConfiguration {
|
||||||
public class XssConfiguration {
|
|
||||||
|
|
||||||
|
private final RequestProperties requestProperties;
|
||||||
private final XssProperties xssProperties;
|
private final XssProperties xssProperties;
|
||||||
private final XssUrlProperties xssUrlProperties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 防XSS注入
|
* 全局过滤器
|
||||||
*
|
|
||||||
* @return FilterRegistrationBean
|
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
|
public FilterRegistrationBean<BladeRequestFilter> bladeFilterRegistration() {
|
||||||
FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
|
FilterRegistrationBean<BladeRequestFilter> registration = new FilterRegistrationBean<>();
|
||||||
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
registration.setDispatcherTypes(DispatcherType.REQUEST);
|
||||||
registration.setFilter(new XssFilter(xssProperties, xssUrlProperties));
|
registration.setFilter(new BladeRequestFilter(requestProperties, xssProperties));
|
||||||
registration.addUrlPatterns("/*");
|
registration.addUrlPatterns("/*");
|
||||||
registration.setName("xssFilter");
|
registration.setName("bladeRequestFilter");
|
||||||
registration.setOrder(Ordered.LOWEST_PRECEDENCE);
|
registration.setOrder(Ordered.LOWEST_PRECEDENCE);
|
||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springblade.core.tool.request;
|
||||||
|
|
||||||
|
import org.springblade.core.tool.utils.WebUtil;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局Request包装
|
||||||
|
*
|
||||||
|
* @author Chill
|
||||||
|
*/
|
||||||
|
public class BladeHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 没被包装过的HttpServletRequest(特殊场景,需要自己过滤)
|
||||||
|
*/
|
||||||
|
private final HttpServletRequest orgRequest;
|
||||||
|
/**
|
||||||
|
* 缓存报文,支持多次读取流
|
||||||
|
*/
|
||||||
|
private byte[] body;
|
||||||
|
|
||||||
|
|
||||||
|
public BladeHttpServletRequestWrapper(HttpServletRequest request) {
|
||||||
|
super(request);
|
||||||
|
orgRequest = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferedReader getReader() throws IOException {
|
||||||
|
return new BufferedReader(new InputStreamReader(getInputStream()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletInputStream getInputStream() throws IOException {
|
||||||
|
if (super.getHeader(HttpHeaders.CONTENT_TYPE) == null) {
|
||||||
|
return super.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (super.getHeader(HttpHeaders.CONTENT_TYPE).startsWith(MediaType.MULTIPART_FORM_DATA_VALUE)) {
|
||||||
|
return super.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body == null) {
|
||||||
|
body = WebUtil.getRequestBody(super.getInputStream()).getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
|
||||||
|
|
||||||
|
return new ServletInputStream() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() {
|
||||||
|
return byteArrayInputStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFinished() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReadListener(ReadListener readListener) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取初始request
|
||||||
|
*
|
||||||
|
* @return HttpServletRequest
|
||||||
|
*/
|
||||||
|
public HttpServletRequest getOrgRequest() {
|
||||||
|
return orgRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取初始request
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return HttpServletRequest
|
||||||
|
*/
|
||||||
|
public static HttpServletRequest getOrgRequest(HttpServletRequest request) {
|
||||||
|
if (request instanceof BladeHttpServletRequestWrapper) {
|
||||||
|
return ((BladeHttpServletRequestWrapper) request).getOrgRequest();
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springblade.core.tool.support.xss;
|
package org.springblade.core.tool.request;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
@ -23,15 +23,15 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XSS过滤
|
* Request全局过滤
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class XssFilter implements Filter {
|
public class BladeRequestFilter implements Filter {
|
||||||
|
|
||||||
|
private final RequestProperties requestProperties;
|
||||||
private final XssProperties xssProperties;
|
private final XssProperties xssProperties;
|
||||||
private final XssUrlProperties xssUrlProperties;
|
|
||||||
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
|
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -42,17 +42,28 @@ public class XssFilter implements Filter {
|
|||||||
@Override
|
@Override
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||||
String path = ((HttpServletRequest) request).getServletPath();
|
String path = ((HttpServletRequest) request).getServletPath();
|
||||||
if (isSkip(path)) {
|
// 跳过 Request 包装
|
||||||
|
if (!requestProperties.getEnabled() || isRequestSkip(path)) {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
} else {
|
}
|
||||||
|
// 默认 Request 包装
|
||||||
|
else if (!xssProperties.getEnabled() || isXssSkip(path)) {
|
||||||
|
BladeHttpServletRequestWrapper bladeRequest = new BladeHttpServletRequestWrapper((HttpServletRequest) request);
|
||||||
|
chain.doFilter(bladeRequest, response);
|
||||||
|
}
|
||||||
|
// Xss Request 包装
|
||||||
|
else {
|
||||||
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
|
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
|
||||||
chain.doFilter(xssRequest, response);
|
chain.doFilter(xssRequest, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSkip(String path) {
|
private boolean isRequestSkip(String path) {
|
||||||
return (xssUrlProperties.getExcludePatterns().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path)))
|
return requestProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
|
||||||
|| (xssProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path)));
|
}
|
||||||
|
|
||||||
|
private boolean isXssSkip(String path) {
|
||||||
|
return xssProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springblade.core.tool.support.xss;
|
package org.springblade.core.tool.request;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
@ -22,14 +22,22 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Xss配置类
|
* Request配置类
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@ConfigurationProperties("blade.xss.url")
|
@ConfigurationProperties("blade.request")
|
||||||
public class XssUrlProperties {
|
public class RequestProperties {
|
||||||
|
|
||||||
private final List<String> excludePatterns = new ArrayList<>();
|
/**
|
||||||
|
* 开启自定义request
|
||||||
|
*/
|
||||||
|
private Boolean enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 放行url
|
||||||
|
*/
|
||||||
|
private List<String> skipUrl = new ArrayList<>();
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.springblade.core.tool.support.xss;
|
package org.springblade.core.tool.request;
|
||||||
|
|
||||||
import org.springblade.core.tool.utils.StringPool;
|
import org.springblade.core.tool.utils.StringPool;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ import java.util.regex.Pattern;
|
|||||||
* @author Cal Hendersen
|
* @author Cal Hendersen
|
||||||
* @author Michael Semb Wever
|
* @author Michael Semb Wever
|
||||||
*/
|
*/
|
||||||
public final class HtmlFilter {
|
public final class XssHtmlFilter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regex flag union representing /si modifiers in php
|
* regex flag union representing /si modifiers in php
|
||||||
@ -128,7 +128,7 @@ public final class HtmlFilter {
|
|||||||
/**
|
/**
|
||||||
* Default constructor.
|
* Default constructor.
|
||||||
*/
|
*/
|
||||||
public HtmlFilter() {
|
public XssHtmlFilter() {
|
||||||
vAllowed = new HashMap<>();
|
vAllowed = new HashMap<>();
|
||||||
|
|
||||||
final ArrayList<String> aAtts = new ArrayList<String>();
|
final ArrayList<String> aAtts = new ArrayList<String>();
|
||||||
@ -158,7 +158,7 @@ public final class HtmlFilter {
|
|||||||
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
|
vAllowedEntities = new String[]{"amp", "gt", "lt", "quot"};
|
||||||
stripComment = true;
|
stripComment = true;
|
||||||
encodeQuotes = true;
|
encodeQuotes = true;
|
||||||
alwaysMakeTags = true;
|
alwaysMakeTags = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,7 +166,7 @@ public final class HtmlFilter {
|
|||||||
*
|
*
|
||||||
* @param debug turn debug on with a true argument
|
* @param debug turn debug on with a true argument
|
||||||
*/
|
*/
|
||||||
public HtmlFilter(final boolean debug) {
|
public XssHtmlFilter(final boolean debug) {
|
||||||
this();
|
this();
|
||||||
vDebug = debug;
|
vDebug = debug;
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ public final class HtmlFilter {
|
|||||||
*
|
*
|
||||||
* @param conf map containing configuration. keys match field names.
|
* @param conf map containing configuration. keys match field names.
|
||||||
*/
|
*/
|
||||||
public HtmlFilter(final Map<String, Object> conf) {
|
public XssHtmlFilter(final Map<String, Object> conf) {
|
||||||
|
|
||||||
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
|
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
|
||||||
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
|
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
|
||||||
@ -243,8 +243,8 @@ public final class HtmlFilter {
|
|||||||
s = escapeComments(s);
|
s = escapeComments(s);
|
||||||
debug(" escapeComments: " + s);
|
debug(" escapeComments: " + s);
|
||||||
|
|
||||||
s = balanceHTML(s);
|
s = balanceHtml(s);
|
||||||
debug(" balanceHTML: " + s);
|
debug(" balanceHtml: " + s);
|
||||||
|
|
||||||
s = checkTags(s);
|
s = checkTags(s);
|
||||||
debug(" checkTags: " + s);
|
debug(" checkTags: " + s);
|
||||||
@ -279,7 +279,7 @@ public final class HtmlFilter {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String balanceHTML(String s) {
|
private String balanceHtml(String s) {
|
||||||
if (alwaysMakeTags) {
|
if (alwaysMakeTags) {
|
||||||
//
|
//
|
||||||
// try and form html
|
// try and form html
|
@ -13,9 +13,10 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springblade.core.tool.support.xss;
|
package org.springblade.core.tool.request;
|
||||||
|
|
||||||
import org.springblade.core.tool.utils.StringUtil;
|
import org.springblade.core.tool.utils.StringUtil;
|
||||||
|
import org.springblade.core.tool.utils.WebUtil;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
@ -27,12 +28,11 @@ import java.io.BufferedReader;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XSS过滤处理
|
* XSS过滤
|
||||||
*
|
*
|
||||||
* @author Chill
|
* @author Chill
|
||||||
*/
|
*/
|
||||||
@ -41,12 +41,15 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
/**
|
/**
|
||||||
* 没被包装过的HttpServletRequest(特殊场景,需要自己过滤)
|
* 没被包装过的HttpServletRequest(特殊场景,需要自己过滤)
|
||||||
*/
|
*/
|
||||||
HttpServletRequest orgRequest;
|
private final HttpServletRequest orgRequest;
|
||||||
|
/**
|
||||||
|
* 缓存报文,支持多次读取流
|
||||||
|
*/
|
||||||
|
private byte[] body;
|
||||||
/**
|
/**
|
||||||
* html过滤
|
* html过滤
|
||||||
*/
|
*/
|
||||||
private final static HtmlFilter HTML_FILTER = new HtmlFilter();
|
private final static XssHtmlFilter HTML_FILTER = new XssHtmlFilter();
|
||||||
|
|
||||||
public XssHttpServletRequestWrapper(HttpServletRequest request) {
|
public XssHttpServletRequestWrapper(HttpServletRequest request) {
|
||||||
super(request);
|
super(request);
|
||||||
@ -60,7 +63,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServletInputStream getInputStream() throws IOException {
|
public ServletInputStream getInputStream() throws IOException {
|
||||||
if (null == super.getHeader(HttpHeaders.CONTENT_TYPE)) {
|
if (super.getHeader(HttpHeaders.CONTENT_TYPE) == null) {
|
||||||
return super.getInputStream();
|
return super.getInputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +71,11 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
return super.getInputStream();
|
return super.getInputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(inputHandlers(super.getInputStream()).getBytes());
|
if (body == null) {
|
||||||
|
body = xssEncode(WebUtil.getRequestBody(super.getInputStream())).getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
|
||||||
|
|
||||||
return new ServletInputStream() {
|
return new ServletInputStream() {
|
||||||
|
|
||||||
@ -93,36 +100,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private String inputHandlers(ServletInputStream servletInputStream) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
BufferedReader reader = null;
|
|
||||||
try {
|
|
||||||
reader = new BufferedReader(new InputStreamReader(servletInputStream, StandardCharsets.UTF_8));
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
sb.append(line);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (servletInputStream != null) {
|
|
||||||
try {
|
|
||||||
servletInputStream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reader != null) {
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return xssEncode(sb.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getParameter(String name) {
|
public String getParameter(String name) {
|
||||||
String value = super.getParameter(xssEncode(name));
|
String value = super.getParameter(xssEncode(name));
|
||||||
@ -138,6 +115,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
if (parameters == null || parameters.length == 0) {
|
if (parameters == null || parameters.length == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < parameters.length; i++) {
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
parameters[i] = xssEncode(parameters[i]);
|
parameters[i] = xssEncode(parameters[i]);
|
||||||
}
|
}
|
||||||
@ -172,7 +150,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取最原始的request
|
* 获取初始request
|
||||||
*
|
*
|
||||||
* @return HttpServletRequest
|
* @return HttpServletRequest
|
||||||
*/
|
*/
|
||||||
@ -181,7 +159,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取最原始的request
|
* 获取初始request
|
||||||
*
|
*
|
||||||
* @param request request
|
* @param request request
|
||||||
* @return HttpServletRequest
|
* @return HttpServletRequest
|
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.springblade.core.tool.support.xss;
|
package org.springblade.core.tool.request;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
@ -26,11 +26,15 @@ import org.springframework.web.context.request.RequestContextHolder;
|
|||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
||||||
|
import javax.servlet.ServletInputStream;
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
|
||||||
@ -268,6 +272,77 @@ public class WebUtil extends org.springframework.web.util.WebUtils {
|
|||||||
return str.replaceAll("&", "&");
|
return str.replaceAll("&", "&");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 request 请求体
|
||||||
|
*
|
||||||
|
* @param servletInputStream servletInputStream
|
||||||
|
* @return body
|
||||||
|
*/
|
||||||
|
public static String getRequestBody(ServletInputStream servletInputStream) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new InputStreamReader(servletInputStream, StandardCharsets.UTF_8));
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (servletInputStream != null) {
|
||||||
|
try {
|
||||||
|
servletInputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reader != null) {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 request 请求内容
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
public static String getRequestContent(HttpServletRequest request) {
|
||||||
|
try {
|
||||||
|
String queryString = request.getQueryString();
|
||||||
|
if (StringUtil.isNotBlank(queryString)) {
|
||||||
|
return new String(queryString.getBytes(Charsets.ISO_8859_1), Charsets.UTF_8).replaceAll("&", "&").replaceAll("%22", "\"");
|
||||||
|
}
|
||||||
|
String charEncoding = request.getCharacterEncoding();
|
||||||
|
if (charEncoding == null) {
|
||||||
|
charEncoding = StringPool.UTF_8;
|
||||||
|
}
|
||||||
|
byte[] buffer = getRequestBody(request.getInputStream()).getBytes();
|
||||||
|
String str = new String(buffer, charEncoding).trim();
|
||||||
|
if (StringUtil.isBlank(str)) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
Enumeration<String> parameterNames = request.getParameterNames();
|
||||||
|
while (parameterNames.hasMoreElements()) {
|
||||||
|
String key = parameterNames.nextElement();
|
||||||
|
String value = request.getParameter(key);
|
||||||
|
StringUtil.appendBuilder(sb, key, "=", value, "&");
|
||||||
|
}
|
||||||
|
str = StringUtil.removeSuffix(sb.toString(), "&");
|
||||||
|
}
|
||||||
|
return str.replaceAll("&", "&");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
return StringPool.EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user