feat: initial iShare project code
This commit is contained in:
44
pigx-common/pigx-common-xss/pom.xml
Normal file
44
pigx-common/pigx-common-xss/pom.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.pig4cloud</groupId>
|
||||
<artifactId>pigx-common</artifactId>
|
||||
<version>5.2.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>pigx-common-xss</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<description>pigx xss 安全过滤插件 基于 JSOUP</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss;
|
||||
|
||||
import com.pig4cloud.pigx.common.xss.config.PigxXssProperties;
|
||||
import com.pig4cloud.pigx.common.xss.core.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* jackson xss 配置
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(PigxXssProperties.class)
|
||||
@ConditionalOnProperty(prefix = PigxXssProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class PigxXssAutoConfiguration implements WebMvcConfigurer {
|
||||
|
||||
private final PigxXssProperties xssProperties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public XssCleaner xssCleaner(PigxXssProperties properties) {
|
||||
return new DefaultXssCleaner(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public FormXssClean formXssClean(PigxXssProperties properties, XssCleaner xssCleaner) {
|
||||
return new FormXssClean(properties, xssCleaner);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(PigxXssProperties properties,
|
||||
XssCleaner xssCleaner) {
|
||||
JacksonXssClean xssClean = new JacksonXssClean(properties, xssCleaner);
|
||||
return builder -> builder.deserializerByType(String.class, xssClean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
List<String> patterns = xssProperties.getPathPatterns();
|
||||
if (patterns.isEmpty()) {
|
||||
patterns.add("/**");
|
||||
}
|
||||
XssCleanInterceptor interceptor = new XssCleanInterceptor(xssProperties);
|
||||
registry.addInterceptor(interceptor).addPathPatterns(patterns)
|
||||
.excludePathPatterns(xssProperties.getPathExcludePatterns()).order(Ordered.LOWEST_PRECEDENCE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Xss配置类
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(PigxXssProperties.PREFIX)
|
||||
public class PigxXssProperties {
|
||||
|
||||
public static final String PREFIX = "security.xss";
|
||||
|
||||
/**
|
||||
* 开启xss,默认关闭: 建议生产环境开启
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* 全局:对文件进行首尾 trim
|
||||
*/
|
||||
private boolean trimText = true;
|
||||
|
||||
/**
|
||||
* 模式:clear 清理(默认),escape 转义
|
||||
*/
|
||||
private Mode mode = Mode.clear;
|
||||
|
||||
/**
|
||||
* [clear 专用] prettyPrint,默认关闭: 保留换行
|
||||
*/
|
||||
private boolean prettyPrint = false;
|
||||
|
||||
/**
|
||||
* [clear 专用] 使用转义,默认关闭
|
||||
*/
|
||||
private boolean enableEscape = false;
|
||||
|
||||
/**
|
||||
* 拦截的路由,默认为空
|
||||
*/
|
||||
private List<String> pathPatterns = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 放行的路由,默认为空
|
||||
*/
|
||||
private List<String> pathExcludePatterns = new ArrayList<>();
|
||||
|
||||
public enum Mode {
|
||||
|
||||
/**
|
||||
* 清理
|
||||
*/
|
||||
clear,
|
||||
/**
|
||||
* 转义
|
||||
*/
|
||||
escape;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.core;
|
||||
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import com.pig4cloud.pigx.common.xss.config.PigxXssProperties;
|
||||
import com.pig4cloud.pigx.common.xss.utils.XssUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.internal.StringUtil;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Entities;
|
||||
import org.jsoup.safety.Cleaner;
|
||||
import org.springframework.web.util.HtmlUtils;
|
||||
|
||||
/**
|
||||
* 默认的 xss 清理器
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class DefaultXssCleaner implements XssCleaner {
|
||||
|
||||
private final PigxXssProperties properties;
|
||||
|
||||
@Override
|
||||
public String clean(String bodyHtml) {
|
||||
// 1. 为空直接返回
|
||||
if (StringUtil.isBlank(bodyHtml)) {
|
||||
return bodyHtml;
|
||||
}
|
||||
PigxXssProperties.Mode mode = properties.getMode();
|
||||
if (PigxXssProperties.Mode.escape == mode) {
|
||||
// html 转义
|
||||
return HtmlUtils.htmlEscape(bodyHtml, CharsetUtil.UTF_8);
|
||||
}
|
||||
else {
|
||||
// jsoup html 清理
|
||||
Document.OutputSettings outputSettings = new Document.OutputSettings()
|
||||
// 2. 转义,没找到关闭的方法,目前这个规则最少
|
||||
.escapeMode(Entities.EscapeMode.xhtml)
|
||||
// 3. 保留换行
|
||||
.prettyPrint(properties.isPrettyPrint());
|
||||
Document dirty = Jsoup.parseBodyFragment(bodyHtml, "");
|
||||
Cleaner cleaner = new Cleaner(XssUtil.WHITE_LIST);
|
||||
Document clean = cleaner.clean(dirty);
|
||||
clean.outputSettings(outputSettings);
|
||||
// 4. 清理后的 html
|
||||
String escapedHtml = clean.body().html();
|
||||
if (properties.isEnableEscape()) {
|
||||
return escapedHtml;
|
||||
}
|
||||
// 5. 反转义
|
||||
return Entities.unescape(escapedHtml);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.core;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.xss.config.PigxXssProperties;
|
||||
import com.pig4cloud.pigx.common.xss.utils.XssUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
/**
|
||||
* 表单 xss 处理
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@ControllerAdvice
|
||||
@RequiredArgsConstructor
|
||||
public class FormXssClean {
|
||||
|
||||
private final PigxXssProperties properties;
|
||||
|
||||
private final XssCleaner xssCleaner;
|
||||
|
||||
@InitBinder
|
||||
public void initBinder(WebDataBinder binder) {
|
||||
// 处理前端传来的表单字符串
|
||||
binder.registerCustomEditor(String.class, new StringPropertiesEditor(xssCleaner, properties));
|
||||
}
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public static class StringPropertiesEditor extends PropertyEditorSupport {
|
||||
|
||||
private final XssCleaner xssCleaner;
|
||||
|
||||
private final PigxXssProperties properties;
|
||||
|
||||
@Override
|
||||
public String getAsText() {
|
||||
Object value = getValue();
|
||||
return value != null ? value.toString() : StrUtil.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
if (text == null) {
|
||||
setValue(null);
|
||||
}
|
||||
else if (XssHolder.isEnabled()) {
|
||||
String value = xssCleaner.clean(XssUtil.trim(text, properties.isTrimText()));
|
||||
setValue(value);
|
||||
log.debug("Request parameter value:{} cleaned up by mica-xss, current value is:{}.", text, value);
|
||||
}
|
||||
else {
|
||||
setValue(XssUtil.trim(text, properties.isTrimText()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.core;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
import com.pig4cloud.pigx.common.xss.config.PigxXssProperties;
|
||||
import com.pig4cloud.pigx.common.xss.utils.XssUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* jackson xss 处理
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class JacksonXssClean extends JsonDeserializer<String> {
|
||||
|
||||
private final PigxXssProperties properties;
|
||||
|
||||
private final XssCleaner xssCleaner;
|
||||
|
||||
@Override
|
||||
public String deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
|
||||
// XSS filter
|
||||
String text = p.getValueAsString();
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
if (XssHolder.isEnabled()) {
|
||||
String value = xssCleaner.clean(XssUtil.trim(text, properties.isTrimText()));
|
||||
log.debug("Json property value:{} cleaned up by mica-xss, current value is:{}.", text, value);
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
return XssUtil.trim(text, properties.isTrimText());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.core;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 忽略 xss
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface XssCleanIgnore {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.core;
|
||||
|
||||
import com.pig4cloud.pigx.common.xss.config.PigxXssProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* xss 处理拦截器
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class XssCleanInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
private final PigxXssProperties xssProperties;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
// 1. 非控制器请求直接跳出
|
||||
if (!(handler instanceof HandlerMethod)) {
|
||||
return true;
|
||||
}
|
||||
// 2. 没有开启
|
||||
if (!xssProperties.isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
// 3. 处理 XssIgnore 注解
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
XssCleanIgnore xssCleanIgnore = AnnotationUtils.getAnnotation(handlerMethod.getMethod(), XssCleanIgnore.class);
|
||||
if (xssCleanIgnore == null) {
|
||||
XssHolder.setEnable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
|
||||
throws Exception {
|
||||
XssHolder.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
XssHolder.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.core;
|
||||
|
||||
/**
|
||||
* xss 清理器
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
public interface XssCleaner {
|
||||
|
||||
/**
|
||||
* 清理 html
|
||||
* @param html html
|
||||
* @return 清理后的数据
|
||||
*/
|
||||
String clean(String html);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
|
||||
* <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 com.pig4cloud.pigx.common.xss.core;
|
||||
|
||||
/**
|
||||
* 利用 ThreadLocal 缓存线程间的数据
|
||||
*
|
||||
* @author L.cm
|
||||
*/
|
||||
class XssHolder {
|
||||
|
||||
private static final ThreadLocal<Boolean> TL = new ThreadLocal<>();
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return Boolean.TRUE.equals(TL.get());
|
||||
}
|
||||
|
||||
public static void setEnable() {
|
||||
TL.set(Boolean.TRUE);
|
||||
}
|
||||
|
||||
public static void remove() {
|
||||
TL.remove();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 此包代码来源至: https://gitee.com/596392912/mica/tree/master/mica-xss
|
||||
*/
|
||||
package com.pig4cloud.pigx.common.xss;
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2020, Michael Yang 杨福海 (fuhai999@gmail.com).
|
||||
* <p>
|
||||
* Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
|
||||
* 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-3.0.txt
|
||||
* <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 com.pig4cloud.pigx.common.xss.utils;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Attribute;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* xss clean
|
||||
*
|
||||
* <p>
|
||||
* 参考自 jpress:https://gitee.com/fuhai/jpress
|
||||
* </p>
|
||||
*
|
||||
* @author L.cm
|
||||
* @author michael
|
||||
*/
|
||||
public class XssUtil {
|
||||
|
||||
public static final HtmlWhitelist WHITE_LIST = new HtmlWhitelist();
|
||||
|
||||
/**
|
||||
* trim 字符串
|
||||
* @param text text
|
||||
* @return 清理后的 text
|
||||
*/
|
||||
public static String trim(String text, boolean trim) {
|
||||
return trim ? StringUtils.trimWhitespace(text) : text;
|
||||
}
|
||||
|
||||
/**
|
||||
* xss 清理
|
||||
* @param html html
|
||||
* @return 清理后的 html
|
||||
*/
|
||||
public static String clean(String html) {
|
||||
if (StringUtils.hasText(html)) {
|
||||
return Jsoup.clean(html, WHITE_LIST);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 做自己的白名单,允许base64的图片通过等
|
||||
*
|
||||
* @author michael
|
||||
*/
|
||||
public static class HtmlWhitelist extends org.jsoup.safety.Whitelist {
|
||||
|
||||
public HtmlWhitelist() {
|
||||
addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "span",
|
||||
"embed", "object", "dl", "dt", "em", "h1", "h2", "h3", "h4", "h5", "h6", "i", "img", "li", "ol",
|
||||
"p", "pre", "q", "small", "strike", "strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th",
|
||||
"thead", "tr", "u", "ul");
|
||||
|
||||
addAttributes("a", "href", "title", "target");
|
||||
addAttributes("blockquote", "cite");
|
||||
addAttributes("col", "span");
|
||||
addAttributes("colgroup", "span");
|
||||
addAttributes("img", "align", "alt", "src", "title");
|
||||
addAttributes("ol", "start");
|
||||
addAttributes("q", "cite");
|
||||
addAttributes("table", "summary");
|
||||
addAttributes("td", "abbr", "axis", "colspan", "rowspan", "width");
|
||||
addAttributes("th", "abbr", "axis", "colspan", "rowspan", "scope", "width");
|
||||
addAttributes("video", "src", "autoplay", "controls", "loop", "muted", "poster", "preload");
|
||||
addAttributes("object", "width", "height", "classid", "codebase");
|
||||
addAttributes("param", "name", "value");
|
||||
addAttributes("embed", "src", "quality", "width", "height", "allowFullScreen", "allowScriptAccess",
|
||||
"flashvars", "name", "type", "pluginspage");
|
||||
|
||||
addAttributes(":all", "class", "style", "height", "width", "type", "id", "name");
|
||||
|
||||
addProtocols("blockquote", "cite", "http", "https");
|
||||
addProtocols("cite", "cite", "http", "https");
|
||||
addProtocols("q", "cite", "http", "https");
|
||||
|
||||
// 如果添加以下的协议,那么href 必须是http、 https 等开头,相对路径则被过滤掉了
|
||||
// addProtocols("a", "href", "ftp", "http", "https", "mailto", "tel");
|
||||
|
||||
// 如果添加以下的协议,那么src必须是http 或者 https 开头,相对路径则被过滤掉了,
|
||||
// 所以必须注释掉,允许相对路径的图片资源
|
||||
// addProtocols("img", "src", "http", "https");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSafeAttribute(String tagName, Element el, Attribute attr) {
|
||||
// 不允许 javascript 开头的 src 和 href
|
||||
if ("src".equalsIgnoreCase(attr.getKey()) || "href".equalsIgnoreCase(attr.getKey())) {
|
||||
String value = attr.getValue();
|
||||
if (StringUtils.hasText(value) && value.toLowerCase().startsWith("javascript")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 允许 base64 的图片内容
|
||||
if ("img".equals(tagName) && "src".equals(attr.getKey()) && attr.getValue().startsWith("data:;base64")) {
|
||||
return true;
|
||||
}
|
||||
return super.isSafeAttribute(tagName, el, attr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
com.pig4cloud.pigx.common.xss.PigxXssAutoConfiguration
|
||||
Reference in New Issue
Block a user