Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
c98e1c14
提交
c98e1c14
authored
1月 13, 2023
作者:
xingyu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix: 修复 xss
上级
9af01c98
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
242 行增加
和
100 行删除
+242
-100
YudaoWebAutoConfiguration.java
...yudao/framework/web/config/YudaoWebAutoConfiguration.java
+37
-3
JsoupXssCleaner.java
...coder/yudao/framework/web/core/clean/JsoupXssCleaner.java
+80
-0
XssCleaner.java
...cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java
+15
-0
XssFilter.java
...cn/iocoder/yudao/framework/web/core/filter/XssFilter.java
+5
-2
XssRequestWrapper.java
...er/yudao/framework/web/core/filter/XssRequestWrapper.java
+46
-95
XssStringJsonDeserializer.java
...ao/framework/web/core/json/XssStringJsonDeserializer.java
+59
-0
没有找到文件。
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
浏览文件 @
c98e1c14
...
@@ -2,15 +2,22 @@ package cn.iocoder.yudao.framework.web.config;
...
@@ -2,15 +2,22 @@ package cn.iocoder.yudao.framework.web.config;
import
cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService
;
import
cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService
;
import
cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum
;
import
cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum
;
import
cn.iocoder.yudao.framework.web.core.clean.JsoupXssCleaner
;
import
cn.iocoder.yudao.framework.web.core.clean.XssCleaner
;
import
cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter
;
import
cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter
;
import
cn.iocoder.yudao.framework.web.core.filter.DemoFilter
;
import
cn.iocoder.yudao.framework.web.core.filter.DemoFilter
;
import
cn.iocoder.yudao.framework.web.core.filter.XssFilter
;
import
cn.iocoder.yudao.framework.web.core.filter.XssFilter
;
import
cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler
;
import
cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler
;
import
cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler
;
import
cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler
;
import
cn.iocoder.yudao.framework.web.core.json.XssStringJsonDeserializer
;
import
cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils
;
import
cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.autoconfigure.AutoConfiguration
;
import
org.springframework.boot.autoconfigure.AutoConfiguration
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
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
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
...
@@ -48,7 +55,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
...
@@ -48,7 +55,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
* 设置 API 前缀,仅仅匹配 controller 包下的
* 设置 API 前缀,仅仅匹配 controller 包下的
*
*
* @param configurer 配置
* @param configurer 配置
* @param api API 配置
* @param api
API 配置
*/
*/
private
void
configurePathMatch
(
PathMatchConfigurer
configurer
,
WebProperties
.
Api
api
)
{
private
void
configurePathMatch
(
PathMatchConfigurer
configurer
,
WebProperties
.
Api
api
)
{
AntPathMatcher
antPathMatcher
=
new
AntPathMatcher
(
"."
);
AntPathMatcher
antPathMatcher
=
new
AntPathMatcher
(
"."
);
...
@@ -104,8 +111,9 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
...
@@ -104,8 +111,9 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
* 创建 XssFilter Bean,解决 Xss 安全问题
* 创建 XssFilter Bean,解决 Xss 安全问题
*/
*/
@Bean
@Bean
public
FilterRegistrationBean
<
XssFilter
>
xssFilter
(
XssProperties
properties
,
PathMatcher
mvcPathMatcher
)
{
@ConditionalOnBean
(
XssCleaner
.
class
)
return
createFilterBean
(
new
XssFilter
(
properties
,
mvcPathMatcher
),
WebFilterOrderEnum
.
XSS_FILTER
);
public
FilterRegistrationBean
<
XssFilter
>
xssFilter
(
XssProperties
properties
,
PathMatcher
pathMatcher
,
XssCleaner
xssCleaner
)
{
return
createFilterBean
(
new
XssFilter
(
properties
,
pathMatcher
,
xssCleaner
),
WebFilterOrderEnum
.
XSS_FILTER
);
}
}
/**
/**
...
@@ -117,6 +125,32 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
...
@@ -117,6 +125,32 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
return
createFilterBean
(
new
DemoFilter
(),
WebFilterOrderEnum
.
DEMO_FILTER
);
return
createFilterBean
(
new
DemoFilter
(),
WebFilterOrderEnum
.
DEMO_FILTER
);
}
}
/**
* Xss 清理者
*
* @return XssCleaner
*/
@ConditionalOnMissingBean
(
XssCleaner
.
class
)
@Bean
public
XssCleaner
xssCleaner
()
{
return
new
JsoupXssCleaner
();
}
/**
* 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤
*
* @return Jackson2ObjectMapperBuilderCustomizer
*/
@Bean
@ConditionalOnMissingBean
(
name
=
"xssJacksonCustomizer"
)
@ConditionalOnBean
(
ObjectMapper
.
class
)
public
Jackson2ObjectMapperBuilderCustomizer
xssJacksonCustomizer
(
XssCleaner
xssCleaner
,
XssProperties
xssProperties
)
{
// 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理
return
builder
->
builder
.
deserializerByType
(
String
.
class
,
new
XssStringJsonDeserializer
(
xssCleaner
,
xssProperties
));
}
private
static
<
T
extends
Filter
>
FilterRegistrationBean
<
T
>
createFilterBean
(
T
filter
,
Integer
order
)
{
private
static
<
T
extends
Filter
>
FilterRegistrationBean
<
T
>
createFilterBean
(
T
filter
,
Integer
order
)
{
FilterRegistrationBean
<
T
>
bean
=
new
FilterRegistrationBean
<>(
filter
);
FilterRegistrationBean
<
T
>
bean
=
new
FilterRegistrationBean
<>(
filter
);
bean
.
setOrder
(
order
);
bean
.
setOrder
(
order
);
...
...
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java
0 → 100644
浏览文件 @
c98e1c14
package
cn
.
iocoder
.
yudao
.
framework
.
web
.
core
.
clean
;
import
org.jsoup.Jsoup
;
import
org.jsoup.nodes.Document
;
import
org.jsoup.safety.Safelist
;
/**
* jsonp 过滤字符串
*/
public
class
JsoupXssCleaner
implements
XssCleaner
{
private
final
Safelist
safelist
;
/**
* 用于在 src 属性使用相对路径时,强制转换为绝对路径。 为空时不处理,值应为绝对路径的前缀(包含协议部分)
*/
private
final
String
baseUri
;
/**
* 无参构造,默认使用 {@link JsoupXssCleaner#buildSafelist} 方法构建一个安全列表
*/
public
JsoupXssCleaner
()
{
this
.
safelist
=
buildSafelist
();
this
.
baseUri
=
""
;
}
public
JsoupXssCleaner
(
Safelist
safelist
)
{
this
.
safelist
=
safelist
;
this
.
baseUri
=
""
;
}
public
JsoupXssCleaner
(
String
baseUri
)
{
this
.
safelist
=
buildSafelist
();
this
.
baseUri
=
baseUri
;
}
public
JsoupXssCleaner
(
Safelist
safelist
,
String
baseUri
)
{
this
.
safelist
=
safelist
;
this
.
baseUri
=
baseUri
;
}
/**
* 构建一个 Xss 清理的 Safelist 规则。
* 基于 Safelist#relaxed() 的基础上:
* 1. 扩展支持了 style 和 class 属性
* 2. a 标签额外支持了 target 属性
* 3. img 标签额外支持了 data 协议,便于支持 base64
*
* @return Safelist
*/
private
Safelist
buildSafelist
()
{
// 使用 jsoup 提供的默认的
Safelist
relaxedSafelist
=
Safelist
.
relaxed
();
// 富文本编辑时一些样式是使用 style 来进行实现的
// 比如红色字体 style="color:red;", 所以需要给所有标签添加 style 属性
// 注意:style 属性会有注入风险 <img STYLE="background-image:url(javascript:alert('XSS'))">
relaxedSafelist
.
addAttributes
(
":all"
,
"style"
,
"class"
);
// 保留 a 标签的 target 属性
relaxedSafelist
.
addAttributes
(
"a"
,
"target"
);
// 支持img 为base64
relaxedSafelist
.
addProtocols
(
"img"
,
"src"
,
"data"
);
// 保留相对路径, 保留相对路径时,必须提供对应的 baseUri 属性,否则依然会被删除
// WHITELIST.preserveRelativeLinks(false);
// 移除 a 标签和 img 标签的一些协议限制,这会导致 xss 防注入失效,如 <img src=javascript:alert("xss")>
// 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径
// WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto");
// WHITELIST.removeProtocols("img", "src", "http", "https");
return
relaxedSafelist
;
}
@Override
public
String
clean
(
String
html
)
{
return
Jsoup
.
clean
(
html
,
baseUri
,
safelist
,
new
Document
.
OutputSettings
().
prettyPrint
(
false
));
}
}
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java
0 → 100644
浏览文件 @
c98e1c14
package
cn
.
iocoder
.
yudao
.
framework
.
web
.
core
.
clean
;
/**
* 对 html 文本中的有 Xss 风险的数据进行清理
*/
public
interface
XssCleaner
{
/**
* 清理有 Xss 风险的文本
*
* @param html 原 html
* @return 清理后的 html
*/
String
clean
(
String
html
);
}
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java
浏览文件 @
c98e1c14
package
cn
.
iocoder
.
yudao
.
framework
.
web
.
core
.
filter
;
package
cn
.
iocoder
.
yudao
.
framework
.
web
.
core
.
filter
;
import
cn.iocoder.yudao.framework.web.config.XssProperties
;
import
cn.iocoder.yudao.framework.web.config.XssProperties
;
import
cn.iocoder.yudao.framework.web.core.clean.XssCleaner
;
import
lombok.AllArgsConstructor
;
import
lombok.AllArgsConstructor
;
import
org.springframework.util.PathMatcher
;
import
org.springframework.util.PathMatcher
;
import
org.springframework.web.filter.OncePerRequestFilter
;
import
org.springframework.web.filter.OncePerRequestFilter
;
...
@@ -13,7 +14,7 @@ import java.io.IOException;
...
@@ -13,7 +14,7 @@ import java.io.IOException;
/**
/**
* Xss 过滤器
* Xss 过滤器
*
*
<p>
* 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/
* 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/
*
*
* @author 芋道源码
* @author 芋道源码
...
@@ -30,10 +31,12 @@ public class XssFilter extends OncePerRequestFilter {
...
@@ -30,10 +31,12 @@ public class XssFilter extends OncePerRequestFilter {
*/
*/
private
final
PathMatcher
pathMatcher
;
private
final
PathMatcher
pathMatcher
;
private
final
XssCleaner
xssCleaner
;
@Override
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
throws
IOException
,
ServletException
{
throws
IOException
,
ServletException
{
filterChain
.
doFilter
(
new
XssRequestWrapper
(
request
),
response
);
filterChain
.
doFilter
(
new
XssRequestWrapper
(
request
,
xssCleaner
),
response
);
}
}
@Override
@Override
...
...
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java
浏览文件 @
c98e1c14
package
cn
.
iocoder
.
yudao
.
framework
.
web
.
core
.
filter
;
package
cn
.
iocoder
.
yudao
.
framework
.
web
.
core
.
filter
;
import
cn.hutool.core.collection.CollUtil
;
import
cn.iocoder.yudao.framework.web.core.clean.XssCleaner
;
import
cn.hutool.core.io.IoUtil
;
import
cn.hutool.core.util.ArrayUtil
;
import
cn.hutool.core.util.ReflectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
cn.hutool.http.HTMLFilter
;
import
cn.iocoder.yudao.framework.common.util.servlet.ServletUtils
;
import
javax.servlet.ReadListener
;
import
javax.servlet.ServletInputStream
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequestWrapper
;
import
javax.servlet.http.HttpServletRequestWrapper
;
import
java.io.BufferedReader
;
import
java.util.LinkedHashMap
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.util.Map
;
import
java.util.Map
;
/**
/**
...
@@ -24,113 +13,75 @@ import java.util.Map;
...
@@ -24,113 +13,75 @@ import java.util.Map;
* @author 芋道源码
* @author 芋道源码
*/
*/
public
class
XssRequestWrapper
extends
HttpServletRequestWrapper
{
public
class
XssRequestWrapper
extends
HttpServletRequestWrapper
{
private
final
XssCleaner
xssCleaner
;
/**
public
XssRequestWrapper
(
HttpServletRequest
request
,
XssCleaner
xssCleaner
)
{
* 基于线程级别的 HTMLFilter 对象,因为它线程非安全
*/
private
static
final
ThreadLocal
<
HTMLFilter
>
HTML_FILTER
=
ThreadLocal
.
withInitial
(()
->
{
HTMLFilter
htmlFilter
=
new
HTMLFilter
();
// 反射修改 encodeQuotes 属性为 false,避免 " 被转移成 " 字符
ReflectUtil
.
setFieldValue
(
htmlFilter
,
"encodeQuotes"
,
false
);
return
htmlFilter
;
});
public
XssRequestWrapper
(
HttpServletRequest
request
)
{
super
(
request
);
super
(
request
);
this
.
xssCleaner
=
xssCleaner
;
}
}
private
static
String
filterXss
(
String
content
)
{
if
(
StrUtil
.
isEmpty
(
content
))
{
return
content
;
}
return
HTML_FILTER
.
get
().
filter
(
content
);
}
// ========== IO 流相关 ==========
@Override
@Override
public
BufferedReader
getReader
()
throws
IOException
{
public
Map
<
String
,
String
[]>
getParameterMap
()
{
return
new
BufferedReader
(
new
InputStreamReader
(
this
.
getInputStream
()));
Map
<
String
,
String
[]>
map
=
new
LinkedHashMap
<>();
Map
<
String
,
String
[]>
parameters
=
super
.
getParameterMap
();
for
(
Map
.
Entry
<
String
,
String
[]>
entry
:
parameters
.
entrySet
())
{
String
[]
values
=
entry
.
getValue
();
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
values
[
i
]
=
xssCleaner
.
clean
(
values
[
i
]);
}
map
.
put
(
entry
.
getKey
(),
values
);
}
return
map
;
}
}
@Override
@Override
public
S
ervletInputStream
getInputStream
()
throws
IOException
{
public
S
tring
[]
getParameterValues
(
String
name
)
{
// 如果非 json 请求,不进行 Xss 处理
String
[]
values
=
super
.
getParameterValues
(
name
);
if
(
!
ServletUtils
.
isJsonRequest
(
this
)
)
{
if
(
values
==
null
)
{
return
super
.
getInputStream
()
;
return
null
;
}
}
int
count
=
values
.
length
;
// 读取内容,并过滤
String
[]
encodedValues
=
new
String
[
count
];
String
content
=
IoUtil
.
readUtf8
(
super
.
getInputStream
());
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
content
=
filterXss
(
content
);
encodedValues
[
i
]
=
xssCleaner
.
clean
(
values
[
i
]);
final
ByteArrayInputStream
newInputStream
=
new
ByteArrayInputStream
(
content
.
getBytes
());
}
// 返回 ServletInputStream
return
encodedValues
;
return
new
ServletInputStream
()
{
@Override
public
int
read
()
{
return
newInputStream
.
read
();
}
@Override
public
boolean
isFinished
()
{
return
true
;
}
@Override
public
boolean
isReady
()
{
return
true
;
}
@Override
public
void
setReadListener
(
ReadListener
readListener
)
{}
};
}
}
// ========== Param 相关 ==========
@Override
@Override
public
String
getParameter
(
String
name
)
{
public
String
getParameter
(
String
name
)
{
String
value
=
super
.
getParameter
(
name
);
String
value
=
super
.
getParameter
(
name
);
return
filterXss
(
value
);
if
(
value
==
null
)
{
return
null
;
}
return
xssCleaner
.
clean
(
value
);
}
}
@Override
@Override
public
String
[]
getParameterValues
(
String
name
)
{
public
Object
getAttribute
(
String
name
)
{
String
[]
values
=
super
.
getParameterValues
(
name
);
Object
value
=
super
.
getAttribute
(
name
);
if
(
ArrayUtil
.
isEmpty
(
values
))
{
if
(
value
instanceof
String
)
{
return
values
;
xssCleaner
.
clean
((
String
)
value
);
}
// 过滤处理
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
values
[
i
]
=
filterXss
(
values
[
i
]);
}
}
return
value
s
;
return
value
;
}
}
@Override
@Override
public
Map
<
String
,
String
[]>
getParameterMap
()
{
public
String
getHeader
(
String
name
)
{
Map
<
String
,
String
[]>
valueMap
=
super
.
getParameterMap
();
String
value
=
super
.
getHeader
(
name
);
if
(
CollUtil
.
isEmpty
(
valueMap
))
{
if
(
value
==
null
)
{
return
valueMap
;
return
null
;
}
// 过滤处理
for
(
Map
.
Entry
<
String
,
String
[]>
entry
:
valueMap
.
entrySet
())
{
String
[]
values
=
entry
.
getValue
();
for
(
int
i
=
0
;
i
<
values
.
length
;
i
++)
{
values
[
i
]
=
filterXss
(
values
[
i
]);
}
}
}
return
valueMap
;
return
xssCleaner
.
clean
(
value
)
;
}
}
// ========== Header 相关 ==========
@Override
@Override
public
String
getHeader
(
String
name
)
{
public
String
getQueryString
()
{
String
value
=
super
.
getHeader
(
name
);
String
value
=
super
.
getQueryString
();
return
filterXss
(
value
);
if
(
value
==
null
)
{
return
null
;
}
return
xssCleaner
.
clean
(
value
);
}
}
}
}
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java
0 → 100644
浏览文件 @
c98e1c14
package
cn
.
iocoder
.
yudao
.
framework
.
web
.
core
.
json
;
import
cn.iocoder.yudao.framework.web.core.clean.XssCleaner
;
import
com.fasterxml.jackson.core.JsonParser
;
import
com.fasterxml.jackson.core.JsonToken
;
import
com.fasterxml.jackson.databind.DeserializationContext
;
import
com.fasterxml.jackson.databind.deser.std.StringDeserializer
;
import
lombok.AllArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
java.io.IOException
;
/**
* XSS 过滤 jackson 反序列化器。
* 在反序列化的过程中,会对字符串进行 XSS 过滤。
*
* @author Hccake
*/
@Slf4j
@AllArgsConstructor
public
class
XssStringJsonDeserializer
extends
StringDeserializer
{
private
final
XssCleaner
xssCleaner
;
@Override
public
String
deserialize
(
JsonParser
p
,
DeserializationContext
ctxt
)
throws
IOException
{
if
(
p
.
hasToken
(
JsonToken
.
VALUE_STRING
))
{
return
xssCleaner
.
clean
(
p
.
getText
());
}
JsonToken
t
=
p
.
currentToken
();
// [databind#381]
if
(
t
==
JsonToken
.
START_ARRAY
)
{
return
_deserializeFromArray
(
p
,
ctxt
);
}
// need to gracefully handle byte[] data, as base64
if
(
t
==
JsonToken
.
VALUE_EMBEDDED_OBJECT
)
{
Object
ob
=
p
.
getEmbeddedObject
();
if
(
ob
==
null
)
{
return
null
;
}
if
(
ob
instanceof
byte
[])
{
return
ctxt
.
getBase64Variant
().
encode
((
byte
[])
ob
,
false
);
}
// otherwise, try conversion using toString()...
return
ob
.
toString
();
}
// 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
if
(
t
==
JsonToken
.
START_OBJECT
)
{
return
ctxt
.
extractScalarFromObject
(
p
,
this
,
_valueClass
);
}
if
(
t
.
isScalarValue
())
{
String
text
=
p
.
getValueAsString
();
return
xssCleaner
.
clean
(
text
);
}
return
(
String
)
ctxt
.
handleUnexpectedToken
(
_valueClass
,
p
);
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论