mirror of
https://gitee.com/liweiyi/ChestnutCMS.git
synced 2025-12-06 16:38:24 +08:00
xss问题修正
This commit is contained in:
parent
bfe5f1ee68
commit
059b7fe848
@ -237,12 +237,6 @@ mybatis-plus:
|
|||||||
xss:
|
xss:
|
||||||
# 过滤开关
|
# 过滤开关
|
||||||
enabled: true
|
enabled: true
|
||||||
mode: clean
|
|
||||||
# 过滤链接
|
|
||||||
urlPatterns:
|
|
||||||
- /system/*
|
|
||||||
- /monitor/*
|
|
||||||
- /tool/*
|
|
||||||
|
|
||||||
xxl:
|
xxl:
|
||||||
job:
|
job:
|
||||||
|
|||||||
@ -220,12 +220,6 @@ mybatis-plus:
|
|||||||
xss:
|
xss:
|
||||||
# 过滤开关
|
# 过滤开关
|
||||||
enabled: true
|
enabled: true
|
||||||
mode: clean
|
|
||||||
# 过滤链接
|
|
||||||
urlPatterns:
|
|
||||||
- /system/*
|
|
||||||
- /monitor/*
|
|
||||||
- /tool/*
|
|
||||||
|
|
||||||
xxl:
|
xxl:
|
||||||
job:
|
job:
|
||||||
|
|||||||
@ -17,10 +17,10 @@ package com.chestnut.common.extend.config;
|
|||||||
|
|
||||||
import com.chestnut.common.extend.config.properties.XssProperties;
|
import com.chestnut.common.extend.config.properties.XssProperties;
|
||||||
import com.chestnut.common.extend.xss.XssDeserializer;
|
import com.chestnut.common.extend.xss.XssDeserializer;
|
||||||
import com.chestnut.common.extend.xss.XssFilter;
|
|
||||||
import com.chestnut.common.extend.xss.XssInterceptor;
|
import com.chestnut.common.extend.xss.XssInterceptor;
|
||||||
import com.chestnut.common.utils.StringUtils;
|
import com.chestnut.common.extend.xss.XssOncePerRequestFilter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||||
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;
|
||||||
@ -30,7 +30,6 @@ import org.springframework.core.Ordered;
|
|||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -43,33 +42,23 @@ public class XssConfig implements WebMvcConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
if (xssProperties.isEnabled()) {
|
if (xssProperties.isEnabled()) {
|
||||||
List<String> urlPatterns = xssProperties.getUrlPatterns();
|
registry.addInterceptor(new XssInterceptor()).addPathPatterns(List.of("/**"))
|
||||||
if (StringUtils.isEmpty(urlPatterns)) {
|
.order(Ordered.HIGHEST_PRECEDENCE);
|
||||||
urlPatterns = List.of("/**");
|
|
||||||
}
|
|
||||||
List<String> excludes = xssProperties.getExcludes();
|
|
||||||
if (StringUtils.isEmpty(excludes)) {
|
|
||||||
excludes = Collections.emptyList();
|
|
||||||
}
|
|
||||||
registry.addInterceptor(new XssInterceptor()).addPathPatterns(urlPatterns)
|
|
||||||
.excludePathPatterns(excludes).order(Ordered.HIGHEST_PRECEDENCE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public FilterRegistrationBean<XssFilter> filterRegistrationBean() {
|
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
|
||||||
FilterRegistrationBean<XssFilter> registrationBean = new FilterRegistrationBean<>();
|
public FilterRegistrationBean<XssOncePerRequestFilter> filterRegistrationBean() {
|
||||||
registrationBean.setFilter(new XssFilter(xssProperties.getMode()));
|
FilterRegistrationBean<XssOncePerRequestFilter> registrationBean = new FilterRegistrationBean<>();
|
||||||
|
registrationBean.setFilter(new XssOncePerRequestFilter(xssProperties.getMode()));
|
||||||
registrationBean.setName("ChestnutXSSFilter");
|
registrationBean.setName("ChestnutXSSFilter");
|
||||||
List<String> urlPatterns = xssProperties.getUrlPatterns();
|
registrationBean.addUrlPatterns("/*");
|
||||||
if (StringUtils.isEmpty(urlPatterns)) {
|
|
||||||
urlPatterns = List.of("/*");
|
|
||||||
}
|
|
||||||
registrationBean.addUrlPatterns(urlPatterns.toArray(String[]::new));
|
|
||||||
return registrationBean;
|
return registrationBean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
|
||||||
public Jackson2ObjectMapperBuilderCustomizer xssCustomizer() {
|
public Jackson2ObjectMapperBuilderCustomizer xssCustomizer() {
|
||||||
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.deserializerByType(String.class,
|
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.deserializerByType(String.class,
|
||||||
new XssDeserializer(xssProperties.getMode()));
|
new XssDeserializer(xssProperties.getMode()));
|
||||||
|
|||||||
@ -15,14 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.chestnut.common.extend.config.properties;
|
package com.chestnut.common.extend.config.properties;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
import com.chestnut.common.extend.enums.XssMode;
|
import com.chestnut.common.extend.enums.XssMode;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ -37,15 +33,5 @@ public class XssProperties {
|
|||||||
/**
|
/**
|
||||||
* 处理方式
|
* 处理方式
|
||||||
*/
|
*/
|
||||||
private XssMode mode;
|
private XssMode mode = XssMode.ESCAPE;
|
||||||
|
|
||||||
/**
|
|
||||||
* 不进行处理的路径
|
|
||||||
*/
|
|
||||||
private List<String> excludes;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理指定路径
|
|
||||||
*/
|
|
||||||
private List<String> urlPatterns;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,14 +26,14 @@ public class XssContextHolder {
|
|||||||
private static final ThreadLocal<Boolean> CONTEXT = new ThreadLocal<>();
|
private static final ThreadLocal<Boolean> CONTEXT = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认:false
|
* 默认:true
|
||||||
*/
|
*/
|
||||||
public static boolean isIgnore() {
|
public static boolean isIgnore() {
|
||||||
return Objects.requireNonNullElse(CONTEXT.get(), false);
|
return Objects.requireNonNullElse(CONTEXT.get(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ignore() {
|
public static void ignore(Boolean ignore) {
|
||||||
CONTEXT.set(true);
|
CONTEXT.set(ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void remove() {
|
public static void remove() {
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
package com.chestnut.common.extend.xss;
|
|
||||||
|
|
||||||
import com.chestnut.common.extend.enums.XssMode;
|
|
||||||
import jakarta.servlet.*;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XSSFilter
|
|
||||||
*
|
|
||||||
* @author 兮玥
|
|
||||||
* @email 190785909@qq.com
|
|
||||||
*/
|
|
||||||
public class XssFilter implements Filter {
|
|
||||||
|
|
||||||
private final XssMode xssMode;
|
|
||||||
|
|
||||||
public XssFilter(XssMode xssMode) {
|
|
||||||
this.xssMode = xssMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
|
||||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
|
||||||
XssHttpServletRequestWrapper wrapper = new XssHttpServletRequestWrapper(request, xssMode);
|
|
||||||
filterChain.doFilter(wrapper, servletResponse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -21,23 +21,13 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class XssInterceptor implements HandlerInterceptor {
|
public class XssInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||||
if (handler instanceof HandlerMethod handlerMethod) {
|
if (handler instanceof HandlerMethod handlerMethod) {
|
||||||
XssIgnore xssIgnore = handlerMethod.getMethodAnnotation(XssIgnore.class);
|
XssContextHolder.ignore(handlerMethod.hasMethodAnnotation(XssIgnore.class));
|
||||||
if (Objects.nonNull(xssIgnore)) {
|
|
||||||
XssContextHolder.ignore();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
|
|
||||||
XssContextHolder.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.chestnut.common.extend.xss;
|
||||||
|
|
||||||
|
import com.chestnut.common.extend.enums.XssMode;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XSSFilter
|
||||||
|
*
|
||||||
|
* @author 兮玥
|
||||||
|
* @email 190785909@qq.com
|
||||||
|
*/
|
||||||
|
public class XssOncePerRequestFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private final XssMode xssMode;
|
||||||
|
|
||||||
|
public XssOncePerRequestFilter(XssMode xssMode) {
|
||||||
|
this.xssMode = xssMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
XssHttpServletRequestWrapper wrapper = new XssHttpServletRequestWrapper(request, xssMode);
|
||||||
|
filterChain.doFilter(wrapper, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user