Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_40988873
jeecg-boot
提交
081c2615
J
jeecg-boot
项目概览
weixin_40988873
/
jeecg-boot
与 Fork 源项目一致
Fork自
jeecg / jeecg-boot
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jeecg-boot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
081c2615
编写于
6月 21, 2021
作者:
JEECG低代码平台
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
HW21-0499 表字典接口存在SQL注入漏洞,增加签名拦截器
上级
f97c6757
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
376 addition
and
1 deletion
+376
-1
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
...e-core/src/main/java/org/jeecg/common/util/DateUtils.java
+5
-1
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthConfiguration.java
.../jeecg/config/sign/interceptor/SignAuthConfiguration.java
+27
-0
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthInterceptor.java
...rg/jeecg/config/sign/interceptor/SignAuthInterceptor.java
+82
-0
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/BodyReaderHttpServletRequestWrapper.java
...config/sign/util/BodyReaderHttpServletRequestWrapper.java
+107
-0
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/HttpUtils.java
...e/src/main/java/org/jeecg/config/sign/util/HttpUtils.java
+106
-0
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/SignUtil.java
...re/src/main/java/org/jeecg/config/sign/util/SignUtil.java
+49
-0
未找到文件。
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/DateUtils.java
浏览文件 @
081c2615
...
@@ -291,7 +291,7 @@ public class DateUtils extends PropertyEditorSupport {
...
@@ -291,7 +291,7 @@ public class DateUtils extends PropertyEditorSupport {
Date
dt
=
new
Date
();
Date
dt
=
new
Date
();
DateFormat
df
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
DateFormat
df
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
String
nowTime
=
df
.
format
(
dt
);
String
nowTime
=
df
.
format
(
dt
);
java
.
sql
.
Timestamp
buydate
=
java
.
sql
.
Timestamp
.
valueOf
(
nowTime
);
Timestamp
buydate
=
Timestamp
.
valueOf
(
nowTime
);
return
buydate
;
return
buydate
;
}
}
...
@@ -616,6 +616,10 @@ public class DateUtils extends PropertyEditorSupport {
...
@@ -616,6 +616,10 @@ public class DateUtils extends PropertyEditorSupport {
return
0
;
return
0
;
}
}
public
static
Long
getCurrentTimestamp
()
{
return
Long
.
valueOf
(
DateUtils
.
yyyymmddhhmmss
.
get
().
format
(
new
Date
()));
}
/**
/**
* String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd
* String类型 转换为Date, 如果参数长度为10 转换格式”yyyy-MM-dd“ 如果参数长度为19 转换格式”yyyy-MM-dd
* HH:mm:ss“ * @param text String类型的时间值
* HH:mm:ss“ * @param text String类型的时间值
...
...
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthConfiguration.java
0 → 100644
浏览文件 @
081c2615
package
org.jeecg.config.sign.interceptor
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.web.servlet.config.annotation.InterceptorRegistry
;
import
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
;
/**
* online 拦截器配置
*/
@Configuration
public
class
SignAuthConfiguration
implements
WebMvcConfigurer
{
@Bean
public
SignAuthInterceptor
signAuthInterceptor
()
{
return
new
SignAuthInterceptor
();
}
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
String
[]
inculudes
=
new
String
[]
{
"/sys/dict/getDictItems/*"
,
"/sys/dict/loadDict/*"
,
"/sys/dict/loadDictOrderByValue/*"
,
"/sys/dict/loadDictItem/*"
,
"/sys/dict/loadTreeData"
,
"/sys/api/queryTableDictItemsByCode"
,
"/sys/api/queryFilterTableDictInfo"
,
"/sys/api/queryTableDictByKeys"
,
"/sys/api/translateDictFromTable"
,
"/sys/api/translateDictFromTableByKeys"
};
registry
.
addInterceptor
(
signAuthInterceptor
()).
addPathPatterns
(
inculudes
);
}
}
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthInterceptor.java
0 → 100644
浏览文件 @
081c2615
package
org.jeecg.config.sign.interceptor
;
import
java.io.PrintWriter
;
import
java.util.SortedMap
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.jeecg.common.api.vo.Result
;
import
org.jeecg.common.util.DateUtils
;
import
org.jeecg.config.sign.util.BodyReaderHttpServletRequestWrapper
;
import
org.jeecg.config.sign.util.HttpUtils
;
import
org.jeecg.config.sign.util.SignUtil
;
import
org.springframework.web.servlet.HandlerInterceptor
;
import
com.alibaba.fastjson.JSON
;
import
lombok.extern.slf4j.Slf4j
;
/**
* 签名拦截器
* @author qinfeng
*/
@Slf4j
public
class
SignAuthInterceptor
implements
HandlerInterceptor
{
/**
* 5分钟有效期
*/
private
final
static
long
MAX_EXPIRE
=
5
*
60
;
@Override
public
boolean
preHandle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Object
handler
)
throws
Exception
{
log
.
debug
(
"request URI = "
+
request
.
getRequestURI
());
HttpServletRequest
requestWrapper
=
new
BodyReaderHttpServletRequestWrapper
(
request
);
//获取全部参数(包括URL和body上的)
SortedMap
<
String
,
String
>
allParams
=
HttpUtils
.
getAllParams
(
requestWrapper
);
//对参数进行签名验证
String
headerSign
=
request
.
getHeader
(
"X-Sign"
);
String
timesTamp
=
request
.
getHeader
(
"X-TIMESTAMP"
);
//1.校验时间有消息
try
{
DateUtils
.
parseDate
(
timesTamp
,
"yyyyMMddHHmmss"
);
}
catch
(
Exception
e
)
{
throw
new
IllegalArgumentException
(
"签名验证失败:X-TIMESTAMP格式必须为:yyyyMMddHHmmss"
);
}
Long
clientTimestamp
=
Long
.
parseLong
(
timesTamp
);
//判断时间戳 timestamp=201808091113
if
((
DateUtils
.
getCurrentTimestamp
()
-
clientTimestamp
)
>
MAX_EXPIRE
)
{
throw
new
IllegalArgumentException
(
"签名验证失败:X-TIMESTAMP已过期"
);
}
//2.校验签名
boolean
isSigned
=
SignUtil
.
verifySign
(
allParams
,
headerSign
);
if
(
isSigned
)
{
log
.
debug
(
"Sign 签名通过!Header Sign : {}"
,
headerSign
);
return
true
;
}
else
{
log
.
error
(
"request URI = "
+
request
.
getRequestURI
());
log
.
error
(
"Sign 签名校验失败!Header Sign : {}"
,
headerSign
);
// //打印日志参数
// Set<String> keySet = allParams.keySet();
// Iterator<String> paramIt = keySet.iterator();
// while(paramIt.hasNext()){
// String pkey = paramIt.next();
// String pval = allParams.get(pkey);
// log.error(" ["+pkey+":"+pval+"] ");
// }
//校验失败返回前端
response
.
setCharacterEncoding
(
"UTF-8"
);
response
.
setContentType
(
"application/json; charset=utf-8"
);
PrintWriter
out
=
response
.
getWriter
();
Result
<?>
result
=
Result
.
error
(
"Sign签名校验失败!"
);
out
.
print
(
JSON
.
toJSON
(
result
));
return
false
;
}
}
}
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/BodyReaderHttpServletRequestWrapper.java
0 → 100644
浏览文件 @
081c2615
package
org.jeecg.config.sign.util
;
import
javax.servlet.ReadListener
;
import
javax.servlet.ServletInputStream
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletRequestWrapper
;
import
java.io.*
;
import
java.nio.charset.Charset
;
/**
* 保存过滤器里面的流
*
* @author show
* @date 10:03 2019/5/30
*/
public
class
BodyReaderHttpServletRequestWrapper
extends
HttpServletRequestWrapper
{
private
final
byte
[]
body
;
public
BodyReaderHttpServletRequestWrapper
(
HttpServletRequest
request
)
{
super
(
request
);
String
sessionStream
=
getBodyString
(
request
);
body
=
sessionStream
.
getBytes
(
Charset
.
forName
(
"UTF-8"
));
}
/**
* 获取请求Body
*
* @param request
* @return
*/
public
String
getBodyString
(
final
ServletRequest
request
)
{
StringBuilder
sb
=
new
StringBuilder
();
try
(
InputStream
inputStream
=
cloneInputStream
(
request
.
getInputStream
());
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
inputStream
,
Charset
.
forName
(
"UTF-8"
))))
{
String
line
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
sb
.
append
(
line
);
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
sb
.
toString
();
}
/**
* Description: 复制输入流</br>
*
* @param inputStream
* @return</br>
*/
public
InputStream
cloneInputStream
(
ServletInputStream
inputStream
)
{
ByteArrayOutputStream
byteArrayOutputStream
=
new
ByteArrayOutputStream
();
byte
[]
buffer
=
new
byte
[
1024
];
int
len
;
try
{
while
((
len
=
inputStream
.
read
(
buffer
))
>
-
1
)
{
byteArrayOutputStream
.
write
(
buffer
,
0
,
len
);
}
byteArrayOutputStream
.
flush
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
new
ByteArrayInputStream
(
byteArrayOutputStream
.
toByteArray
());
}
@Override
public
BufferedReader
getReader
()
{
return
new
BufferedReader
(
new
InputStreamReader
(
getInputStream
()));
}
@Override
public
ServletInputStream
getInputStream
()
{
final
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
body
);
return
new
ServletInputStream
()
{
@Override
public
int
read
()
{
return
bais
.
read
();
}
@Override
public
boolean
isFinished
()
{
return
false
;
}
@Override
public
boolean
isReady
()
{
return
false
;
}
@Override
public
void
setReadListener
(
ReadListener
readListener
)
{
}
};
}
}
\ No newline at end of file
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/HttpUtils.java
0 → 100644
浏览文件 @
081c2615
package
org.jeecg.config.sign.util
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.io.UnsupportedEncodingException
;
import
java.net.URLDecoder
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.SortedMap
;
import
java.util.TreeMap
;
import
javax.servlet.http.HttpServletRequest
;
import
org.jeecg.common.util.oConvertUtils
;
import
org.springframework.http.HttpMethod
;
import
com.alibaba.fastjson.JSONObject
;
/**
* http 工具类 获取请求中的参数
*
* @author show
* @date 14:23 2019/5/29
*/
public
class
HttpUtils
{
/**
* 将URL的参数和body参数合并
*
* @author show
* @date 14:24 2019/5/29
* @param request
*/
public
static
SortedMap
<
String
,
String
>
getAllParams
(
HttpServletRequest
request
)
throws
IOException
{
SortedMap
<
String
,
String
>
result
=
new
TreeMap
<>();
// 获取URL上最后带逗号的参数变量 sys/dict/getDictItems/sys_user,realname,username
String
pathVariable
=
request
.
getRequestURI
().
substring
(
request
.
getRequestURI
().
lastIndexOf
(
"/"
)+
1
);
if
(
pathVariable
.
contains
(
","
)){
result
.
put
(
SignUtil
.
xPathVariable
,
pathVariable
);
}
// 获取URL上的参数
Map
<
String
,
String
>
urlParams
=
getUrlParams
(
request
);
for
(
Map
.
Entry
entry
:
urlParams
.
entrySet
())
{
result
.
put
((
String
)
entry
.
getKey
(),
(
String
)
entry
.
getValue
());
}
Map
<
String
,
String
>
allRequestParam
=
new
HashMap
<>(
16
);
// get请求不需要拿body参数
if
(!
HttpMethod
.
GET
.
name
().
equals
(
request
.
getMethod
()))
{
allRequestParam
=
getAllRequestParam
(
request
);
}
// 将URL的参数和body参数进行合并
if
(
allRequestParam
!=
null
)
{
for
(
Map
.
Entry
entry
:
allRequestParam
.
entrySet
())
{
result
.
put
((
String
)
entry
.
getKey
(),
(
String
)
entry
.
getValue
());
}
}
return
result
;
}
/**
* 获取 Body 参数
*
* @author show
* @date 15:04 2019/5/30
* @param request
*/
public
static
Map
<
String
,
String
>
getAllRequestParam
(
final
HttpServletRequest
request
)
throws
IOException
{
BufferedReader
reader
=
new
BufferedReader
(
new
InputStreamReader
(
request
.
getInputStream
()));
String
str
=
""
;
StringBuilder
wholeStr
=
new
StringBuilder
();
// 一行一行的读取body体里面的内容;
while
((
str
=
reader
.
readLine
())
!=
null
)
{
wholeStr
.
append
(
str
);
}
// 转化成json对象
return
JSONObject
.
parseObject
(
wholeStr
.
toString
(),
Map
.
class
);
}
/**
* 将URL请求参数转换成Map
*
* @author show
* @param request
*/
public
static
Map
<
String
,
String
>
getUrlParams
(
HttpServletRequest
request
)
{
Map
<
String
,
String
>
result
=
new
HashMap
<>(
16
);
if
(
oConvertUtils
.
isEmpty
(
request
.
getQueryString
())){
return
result
;
}
String
param
=
""
;
try
{
param
=
URLDecoder
.
decode
(
request
.
getQueryString
(),
"utf-8"
);
}
catch
(
UnsupportedEncodingException
e
)
{
e
.
printStackTrace
();
}
String
[]
params
=
param
.
split
(
"&"
);
for
(
String
s
:
params
)
{
int
index
=
s
.
indexOf
(
"="
);
result
.
put
(
s
.
substring
(
0
,
index
),
s
.
substring
(
index
+
1
));
}
return
result
;
}
}
\ No newline at end of file
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/SignUtil.java
0 → 100644
浏览文件 @
081c2615
package
org.jeecg.config.sign.util
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.util.DigestUtils
;
import
org.springframework.util.StringUtils
;
import
java.util.SortedMap
;
/**
* 签名工具类
*
* @author show
* @date 10:01 2019/5/30
*/
@Slf4j
public
class
SignUtil
{
//签名密钥串(前后端要一致,正式发布请自行修改)
private
static
final
String
signatureSecret
=
"dd05f1c54d63749eda95f9fa6d49v442a"
;
public
static
final
String
xPathVariable
=
"x-path-variable"
;
/**
* @param params
* 所有的请求参数都会在这里进行排序加密
* @return 验证签名结果
*/
public
static
boolean
verifySign
(
SortedMap
<
String
,
String
>
params
,
String
headerSign
)
{
if
(
params
==
null
||
StringUtils
.
isEmpty
(
headerSign
))
{
return
false
;
}
// 把参数加密
String
paramsSign
=
getParamsSign
(
params
);
log
.
info
(
"Param Sign : {}"
,
paramsSign
);
return
!
StringUtils
.
isEmpty
(
paramsSign
)
&&
headerSign
.
equals
(
paramsSign
);
}
/**
* @param params
* 所有的请求参数都会在这里进行排序加密
* @return 得到签名
*/
public
static
String
getParamsSign
(
SortedMap
<
String
,
String
>
params
)
{
//去掉 Url 里的时间戳
params
.
remove
(
"_t"
);
String
paramsJsonStr
=
JSONObject
.
toJSONString
(
params
);
log
.
info
(
"Param paramsJsonStr : {}"
,
paramsJsonStr
);
return
DigestUtils
.
md5DigestAsHex
((
paramsJsonStr
+
signatureSecret
).
getBytes
()).
toUpperCase
();
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录