Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nouiWithSpringMVC
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gechengyang
nouiWithSpringMVC
Commits
b1384b46
Commit
b1384b46
authored
Oct 03, 2020
by
WeiCong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
调整数据安全框架后台部分
增加数据安全交易配置
parent
e32e0dec
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
110 additions
and
47 deletions
+110
-47
AbstractCommonController.java
...resentation/noui/controller/AbstractCommonController.java
+26
-29
DataSecurityUtil.java
...java/org/sss/presentation/noui/util/DataSecurityUtil.java
+77
-18
security.properties
src/main/resources/security.properties
+7
-0
No files found.
src/main/java/org/sss/presentation/noui/controller/AbstractCommonController.java
View file @
b1384b46
...
@@ -54,35 +54,9 @@ public abstract class AbstractCommonController {
...
@@ -54,35 +54,9 @@ public abstract class AbstractCommonController {
NoUiContext
context
=
null
;
NoUiContext
context
=
null
;
Result
ret
=
null
;
Result
ret
=
null
;
String
serverEnc
=
null
;
String
serverEnc
=
null
;
boolean
bgidflag
=
false
;
try
{
try
{
NoUiRequest
noUiRequest
=
new
NoUiRequest
(
request
,
mappingUrl
,
dataMap
);
NoUiRequest
noUiRequest
=
new
NoUiRequest
(
request
,
mappingUrl
,
dataMap
);
//数据安全性拦截处理
if
(
noUiRequest
.
isSecurity
()){
Map
<
String
,
?>
paramsMap
=
noUiRequest
.
getParamsMap
();
if
(
paramsMap
.
containsKey
(
DataSecurityUtil
.
CHECK_KEY
)){
//加密操作(场景:用户查询指定信息时调用,后续会做修改,删除等操作)
List
<
String
>
parlst
=
(
List
<
String
>)
paramsMap
.
get
(
DataSecurityUtil
.
CHECK_KEY
);
String
[]
pars
=
parlst
.
toArray
(
new
String
[
0
]);
if
(
ArrayUtils
.
isEmpty
(
pars
)){
Result
rt
=
new
Result
(
ErrorCodes
.
ERROR
,
"调用安全请求方式,但未设置校验数据"
,
null
,
noUiVersion
.
getVersion
());
return
rt
;
}
serverEnc
=
DataSecurityUtil
.
encrypt
(
pars
,
noUiRequest
.
getUserId
());
bgidflag
=
true
;
}
else
{
//合法性校验操作(场景:用户做修改、删除时调用)
serverEnc
=
(
String
)
paramsMap
.
get
(
DataSecurityUtil
.
BACKGROUND_ID
);
String
clientEnc
=
(
String
)
paramsMap
.
get
(
DataSecurityUtil
.
FRONT_ID
);
String
errmsg
=
null
;
if
((
errmsg
=
DataSecurityUtil
.
checkIllegalData
(
serverEnc
,
clientEnc
,
noUiRequest
.
getUserId
()))!=
null
){
Result
rt
=
new
Result
(
ErrorCodes
.
ERROR
,
errmsg
,
null
,
noUiVersion
.
getVersion
());
return
rt
;
}
}
}
Alias
alias
=
new
Alias
(
mappingUrl
);
Alias
alias
=
new
Alias
(
mappingUrl
);
String
trnName
=
alias
.
getTrnName
();
String
trnName
=
alias
.
getTrnName
();
Map
<
String
,
?>
paramsMap
=
noUiRequest
.
getParamsMap
();
Map
<
String
,
?>
paramsMap
=
noUiRequest
.
getParamsMap
();
...
@@ -114,6 +88,22 @@ public abstract class AbstractCommonController {
...
@@ -114,6 +88,22 @@ public abstract class AbstractCommonController {
// 模型赋值
// 模型赋值
NoUiPresentationUtil
.
hanleInput
(
context
,
noUiRequest
,
alias
);
NoUiPresentationUtil
.
hanleInput
(
context
,
noUiRequest
,
alias
);
//数据安全性拦截-篡改数据拦截
if
(
DataSecurityUtil
.
isSafeMode
()
&&
noUiRequest
.
isSecurity
()){
if
(
paramsMap
.
containsKey
(
DataSecurityUtil
.
BACKGROUND_ID
)){
String
[]
clientpars
=
DataSecurityUtil
.
getSafeConfigByTrnName
(
context
,
trnName
);
if
(!
ArrayUtils
.
isEmpty
(
clientpars
)){
//合法性校验操作(场景:用户做修改、删除时调用)
serverEnc
=
(
String
)
paramsMap
.
get
(
DataSecurityUtil
.
BACKGROUND_ID
);
String
errmsg
=
null
;
if
((
errmsg
=
DataSecurityUtil
.
checkIllegalData
(
serverEnc
,
clientpars
,
noUiRequest
.
getUserId
()))!=
null
){
Result
rt
=
new
Result
(
ErrorCodes
.
ERROR
,
errmsg
,
null
,
noUiVersion
.
getVersion
());
return
rt
;
}
}
}
}
if
(
eventType
.
equals
(
ON_CLICK
))
{
if
(
eventType
.
equals
(
ON_CLICK
))
{
IBaseObject
dataField
=
baseObject
(
context
,
noUiRequest
,
alias
);
IBaseObject
dataField
=
baseObject
(
context
,
noUiRequest
,
alias
);
((
IDatafield
<?>)
dataField
).
invokeEventRules
(
context
,
EventType
.
ON_CLICK
,
null
);
((
IDatafield
<?>)
dataField
).
invokeEventRules
(
context
,
EventType
.
ON_CLICK
,
null
);
...
@@ -159,9 +149,16 @@ public abstract class AbstractCommonController {
...
@@ -159,9 +149,16 @@ public abstract class AbstractCommonController {
Map
<
String
,
Object
>
afterReturnData
=
handleReturnData
(
eventType
,
context
,
noUiRequest
,
alias
);
Map
<
String
,
Object
>
afterReturnData
=
handleReturnData
(
eventType
,
context
,
noUiRequest
,
alias
);
//增加数据安全性代码
//数据安全性拦截-篡改数据加密
if
(
bgidflag
){
if
(
DataSecurityUtil
.
isSafeMode
()
&&
noUiRequest
.
isSecurity
()){
afterReturnData
.
put
(
DataSecurityUtil
.
BACKGROUND_ID
,
serverEnc
);
if
(!
paramsMap
.
containsKey
(
DataSecurityUtil
.
BACKGROUND_ID
)){
//加密操作(场景:用户查询指定信息时调用,后续会做修改,删除等操作)
String
[]
pars
=
DataSecurityUtil
.
getSafeConfigByTrnName
(
context
,
trnName
);
if
(!
ArrayUtils
.
isEmpty
(
pars
)){
serverEnc
=
DataSecurityUtil
.
encrypt
(
pars
,
noUiRequest
.
getUserId
());
afterReturnData
.
put
(
DataSecurityUtil
.
BACKGROUND_ID
,
serverEnc
);
}
}
}
}
ret
=
ResultUtil
.
result
(
NoUiPresentationUtil
.
retCode
(
context
),
NoUiPresentationUtil
.
retMsg
(
context
),
afterReturnData
,
ret
=
ResultUtil
.
result
(
NoUiPresentationUtil
.
retCode
(
context
),
NoUiPresentationUtil
.
retMsg
(
context
),
afterReturnData
,
...
...
src/main/java/org/sss/presentation/noui/util/DataSecurityUtil.java
View file @
b1384b46
...
@@ -3,11 +3,13 @@ package org.sss.presentation.noui.util;
...
@@ -3,11 +3,13 @@ package org.sss.presentation.noui.util;
import
log.Log
;
import
log.Log
;
import
log.LogFactory
;
import
log.LogFactory
;
import
org.apache.commons.lang.ArrayUtils
;
import
org.apache.commons.lang.ArrayUtils
;
import
org.springframework.core.io.ClassPathResource
;
import
org.sss.common.model.IBaseObject
;
import
org.sss.common.model.IDatafield
;
import
org.sss.presentation.noui.common.Constants
;
import
org.sss.presentation.noui.common.Constants
;
import
org.sss.presentation.noui.context.NoUiContext
;
import
java.util.Arrays
;
import
java.util.*
;
import
java.util.List
;
import
java.util.UUID
;
/**
/**
* 前后端数据安全校验,用来防止前端数据被篡改后送到服务端引起的安全问题
* 前后端数据安全校验,用来防止前端数据被篡改后送到服务端引起的安全问题
...
@@ -16,17 +18,74 @@ import java.util.UUID;
...
@@ -16,17 +18,74 @@ import java.util.UUID;
public
class
DataSecurityUtil
{
public
class
DataSecurityUtil
{
public
static
final
String
ENCRYPT_ERROR
=
"encrypt exception"
;
public
static
final
String
ENCRYPT_ERROR
=
"encrypt exception"
;
public
static
final
String
DECRYPT_ERROR
=
"decrypt exception"
;
public
static
final
String
DECRYPT_ERROR
=
"decrypt exception"
;
public
static
final
String
FIX_STR
=
"`wD4+-@hh"
;
public
static
final
String
CHECK_KEY
=
"__checkkey__"
;
public
static
final
String
FRONT_ID
=
"__fid__"
;
public
static
final
String
BACKGROUND_ID
=
"__bgid__"
;
public
static
final
String
BACKGROUND_ID
=
"__bgid__"
;
public
static
final
String
ERROR_SERVERENC_NULL
=
"[服务端密文串异常],数据存在篡改风险!"
;
public
static
final
String
ERROR_SERVERENC_NULL
=
"[服务端密文串异常],数据存在篡改风险!"
;
public
static
final
String
ERROR_DYNAMICSALT_NULL
=
"[获取的动态盐不存在],可能存在后台暴力破解风险,从而导致数据存在篡改被篡改的风险!"
;
public
static
final
String
ERROR_DYNAMICSALT_NULL
=
"[获取的动态盐不存在],可能存在后台暴力破解风险,从而导致数据存在篡改被篡改的风险!"
;
public
static
final
String
ERROR_DYNAMICSALT_EXCEPTION
=
"[获取动态盐异常],可能redis异常,从而导致数据存在篡改被篡改的风险!"
;
public
static
final
String
ERROR_DYNAMICSALT_EXCEPTION
=
"[获取动态盐异常],可能redis异常,从而导致数据存在篡改被篡改的风险!"
;
public
static
final
String
ERROR_AES_DECODE
=
"[服务端密文串解密失败],数据存在篡改风险!"
;
public
static
final
String
ERROR_AES_DECODE
=
"[服务端密文串解密失败],数据存在篡改风险!"
;
public
static
final
String
ERROR_NOTMATCH
=
"[服务端密文串解密后的值与客户端密文串不同],数据存在篡改风险!"
;
public
static
final
String
ERROR_NOTMATCH
=
"[服务端密文串解密后的值与客户端密文串不同],数据存在篡改风险!"
;
public
static
final
String
SWITCH_KEY
=
"switch"
;
public
static
final
String
SAFE_MODE
=
"ON"
;
public
static
final
String
UNSAFE_MODE
=
"OFF"
;
private
static
HashMap
<
String
,
String
>
securityConfig
;
private
static
final
Log
log
=
LogFactory
.
getLog
(
DataSecurityUtil
.
class
);
private
static
final
Log
log
=
LogFactory
.
getLog
(
DataSecurityUtil
.
class
);
static
{
ClassPathResource
resource
=
new
ClassPathResource
(
"security.properties"
,
DataSecurityUtil
.
class
);
try
{
securityConfig
=
new
HashMap
<
String
,
String
>((
Map
)
PropertyUtil
.
load
(
"security.properties"
));
}
catch
(
Exception
e
)
{
//降级处理
log
.
warn
(
"加载安全配置文件失败:"
+
e
.
getMessage
());
securityConfig
=
new
HashMap
<
String
,
String
>();
securityConfig
.
put
(
SWITCH_KEY
,
UNSAFE_MODE
);
}
}
/**
* 是否开启安全模式,开启后会对前端传输的数据根据配置文件做篡改性校验
* @return true表示开启;false不开启
*/
public
static
boolean
isSafeMode
(){
return
SAFE_MODE
.
equalsIgnoreCase
(
securityConfig
.
get
(
SWITCH_KEY
));
}
/**
* 获取指定交易的安全配置
* @param context 交易上下文
* @param trnName 交易名
* @return 指定交易的安全配置信息
*/
public
static
String
[]
getSafeConfigByTrnName
(
NoUiContext
context
,
String
trnName
){
String
safeConfigByTrnName
=
securityConfig
.
get
(
trnName
);
if
(!
StringUtil
.
isEmpty
(
safeConfigByTrnName
)){
String
[]
urls
=
safeConfigByTrnName
.
split
(
","
);
String
[]
pars
=
new
String
[
urls
.
length
];
for
(
int
i
=
0
;
i
<
urls
.
length
;
i
++){
String
url
=
urls
[
i
];
IBaseObject
baseObject
=
context
.
getSession
().
getBaseObject
(
context
.
getRoot
(),
url
);
if
(
null
==
baseObject
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
"交易["
).
append
(
trnName
).
append
(
"]对应的待校验字段["
);
sb
.
append
(
url
).
append
(
"]在模型中未找到"
);
log
.
error
(
sb
.
toString
());
}
else
{
if
(
baseObject
instanceof
IDatafield
<?>)
{
IDatafield
<
Object
>
dataField
=
(
IDatafield
<
Object
>)
baseObject
;
pars
[
i
]=
dataField
.
getValue
().
toString
();
}
else
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
"交易["
).
append
(
trnName
).
append
(
"]对应的待校验字段["
);
sb
.
append
(
url
).
append
(
"]在模型中不是IDatafield类型"
);
log
.
error
(
sb
.
toString
());
}
}
}
return
pars
;
}
return
null
;
}
/**
/**
* 对不可篡改参数做加签处理
* 对不可篡改参数做加签处理
*
*
...
@@ -43,12 +102,7 @@ public class DataSecurityUtil {
...
@@ -43,12 +102,7 @@ public class DataSecurityUtil {
log
.
warn
(
"设置动态盐失败:"
+
e
.
getMessage
());
log
.
warn
(
"设置动态盐失败:"
+
e
.
getMessage
());
return
ENCRYPT_ERROR
;
return
ENCRYPT_ERROR
;
}
}
String
content
=
null
;
String
content
=
preHandle
(
pars
);
try
{
content
=
preHandle
(
pars
);
}
catch
(
Exception
e
)
{
log
.
warn
(
"数据md5加密失败:"
+
e
.
getMessage
());
}
content
=
AESUtil
.
encrypt
(
content
,
dynamicSalt
.
pwd
,
dynamicSalt
.
iv
);
content
=
AESUtil
.
encrypt
(
content
,
dynamicSalt
.
pwd
,
dynamicSalt
.
iv
);
return
content
==
null
?
ENCRYPT_ERROR
:
content
;
return
content
==
null
?
ENCRYPT_ERROR
:
content
;
}
}
...
@@ -57,11 +111,11 @@ public class DataSecurityUtil {
...
@@ -57,11 +111,11 @@ public class DataSecurityUtil {
* 判断数据是否篡改
* 判断数据是否篡改
*
*
* @param serverEnc 服务端产生的密文串
* @param serverEnc 服务端产生的密文串
* @param client
Enc 客户端产生的密文串
* @param client
pars 客户端待校验参数
* @param userId 用户id
* @param userId 用户id
* @return 返回错误描述
* @return 返回错误描述
*/
*/
public
static
String
checkIllegalData
(
String
serverEnc
,
String
clientEnc
,
String
userId
)
{
public
static
String
checkIllegalData
(
String
serverEnc
,
String
[]
clientpars
,
String
userId
)
{
//1.判断服务端的密文串是否异常
//1.判断服务端的密文串是否异常
if
(
StringUtil
.
isEmpty
(
serverEnc
)
||
ENCRYPT_ERROR
.
equals
(
serverEnc
)){
if
(
StringUtil
.
isEmpty
(
serverEnc
)
||
ENCRYPT_ERROR
.
equals
(
serverEnc
)){
log
.
warn
(
ERROR_SERVERENC_NULL
);
log
.
warn
(
ERROR_SERVERENC_NULL
);
...
@@ -80,14 +134,21 @@ public class DataSecurityUtil {
...
@@ -80,14 +134,21 @@ public class DataSecurityUtil {
return
ERROR_DYNAMICSALT_EXCEPTION
;
return
ERROR_DYNAMICSALT_EXCEPTION
;
}
}
serverEnc
=
decrypt
(
serverEnc
,
dynamicSalt
);
serverEnc
=
decrypt
(
serverEnc
,
dynamicSalt
);
if
(
StringUtil
.
isEmpty
(
serverEnc
)
||
DECRYPT_ERROR
.
equals
(
serverEnc
)){
if
(
StringUtil
.
isEmpty
(
serverEnc
)
||
DECRYPT_ERROR
.
equals
(
serverEnc
)){
log
.
warn
(
ERROR_AES_DECODE
);
log
.
warn
(
ERROR_AES_DECODE
);
return
ERROR_AES_DECODE
;
return
ERROR_AES_DECODE
;
}
}
String
clientEnc
=
preHandle
(
clientpars
);
if
(!
serverEnc
.
equals
(
clientEnc
)){
if
(!
serverEnc
.
equals
(
clientEnc
)){
log
.
warn
(
ERROR_NOTMATCH
);
log
.
warn
(
ERROR_NOTMATCH
);
return
ERROR_NOTMATCH
;
return
ERROR_NOTMATCH
;
}
}
try
{
RedisUtil
.
delete
(
getCacheSaltKey
(
userId
));
}
catch
(
Exception
e
)
{
log
.
warn
(
"删除失效盐出现异常:"
+
e
.
getMessage
());
}
return
null
;
return
null
;
}
}
...
@@ -106,13 +167,12 @@ public class DataSecurityUtil {
...
@@ -106,13 +167,12 @@ public class DataSecurityUtil {
return
content
==
null
?
DECRYPT_ERROR
:
content
;
return
content
==
null
?
DECRYPT_ERROR
:
content
;
}
}
private
static
String
preHandle
(
String
[]
pars
)
throws
Exception
{
private
static
String
preHandle
(
String
[]
pars
){
if
(
ArrayUtils
.
isEmpty
(
pars
))
{
if
(
ArrayUtils
.
isEmpty
(
pars
))
{
return
null
;
return
null
;
}
}
List
<
String
>
lst
=
Arrays
.
asList
(
pars
);
List
<
String
>
lst
=
Arrays
.
asList
(
pars
);
String
md5
=
String
.
join
(
FIX_STR
,
lst
);
String
md5
=
String
.
join
(
""
,
lst
);
md5
=
StringUtil
.
encryptMD5
(
md5
);
return
md5
;
return
md5
;
}
}
...
@@ -121,7 +181,6 @@ public class DataSecurityUtil {
...
@@ -121,7 +181,6 @@ public class DataSecurityUtil {
Object
obj
=
RedisUtil
.
get
(
key
);
Object
obj
=
RedisUtil
.
get
(
key
);
DynamicSalt
rs
=
parseDynamicSalt
(
obj
);
DynamicSalt
rs
=
parseDynamicSalt
(
obj
);
if
(
rs
!=
null
){
if
(
rs
!=
null
){
RedisUtil
.
delete
(
key
);
return
rs
;
return
rs
;
}
}
return
null
;
return
null
;
...
...
src/main/resources/security.properties
0 → 100644
View file @
b1384b46
#安全开关(ON:开;OFF:关)
switch
=
ON
#客户管理——修改
dbepty
=
\\
ptygrp
\\
rec
\\
inr,
\\
ptygrp
\\
rec
\\
extkey
#客户管理——删除
dbdpty
=
\\
ptygrp
\\
rec
\\
inr
#
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment