Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-communication
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-communication
Commits
655980ca
Commit
655980ca
authored
Aug 03, 2026
by
zhangxingmin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
push
parent
95df52a3
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
699 additions
and
116 deletions
+699
-116
yd-communication-api/src/main/java/com/yd/communication/api/config/AsyncConfig.java
+23
-0
yd-communication-api/src/main/java/com/yd/communication/api/controller/ApiCoDesensitizationRuleController.java
+51
-0
yd-communication-api/src/main/java/com/yd/communication/api/controller/CoDesensitizationRuleController.java
+0
-18
yd-communication-api/src/main/java/com/yd/communication/api/service/ApiCoDesensitizationRuleService.java
+12
-0
yd-communication-api/src/main/java/com/yd/communication/api/service/impl/ApiCoDesensitizationRuleServiceImpl.java
+65
-0
yd-communication-api/src/main/java/com/yd/communication/api/service/impl/ApiCoSessionServiceImpl.java
+50
-6
yd-communication-api/src/main/java/com/yd/communication/api/service/impl/ApiRecordingTaskServiceImpl.java
+29
-2
yd-communication-api/src/main/java/com/yd/communication/api/utils/ClientInfoUtils.java
+84
-0
yd-communication-api/src/main/java/com/yd/communication/api/utils/IpContextHolder.java
+55
-0
yd-communication-api/src/main/java/com/yd/communication/api/websocket/CoWebSocketServer.java
+64
-4
yd-communication-feign/src/main/java/com/yd/communication/feign/client/ApiCoDesensitizationRuleFeignClient.java
+35
-0
yd-communication-feign/src/main/java/com/yd/communication/feign/fallback/ApiCoDesensitizationRuleFeignFallbackFactory.java
+31
-0
yd-communication-feign/src/main/java/com/yd/communication/feign/response/desensitization/ApiCoDesensitizationRuleResponse.java
+67
-0
yd-communication-service/src/main/java/com/yd/communication/service/service/ICoDesensitizationRuleService.java
+27
-8
yd-communication-service/src/main/java/com/yd/communication/service/service/impl/CoDesensitizationRuleServiceImpl.java
+104
-78
yd-communication-service/src/main/java/com/yd/communication/service/service/impl/CoOperationLogServiceImpl.java
+2
-0
No files found.
yd-communication-api/src/main/java/com/yd/communication/api/config/AsyncConfig.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
api
.
config
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
;
import
java.util.concurrent.Executor
;
@Configuration
public
class
AsyncConfig
{
@Bean
(
name
=
"communicationExecutor"
)
public
Executor
taskExecutor
()
{
ThreadPoolTaskExecutor
executor
=
new
ThreadPoolTaskExecutor
();
executor
.
setCorePoolSize
(
5
);
// 核心线程数
executor
.
setMaxPoolSize
(
10
);
// 最大线程数
executor
.
setQueueCapacity
(
100
);
// 队列容量
executor
.
setThreadNamePrefix
(
"communication-"
);
// 线程名前缀
executor
.
initialize
();
return
executor
;
}
}
\ No newline at end of file
yd-communication-api/src/main/java/com/yd/communication/api/controller/ApiCoDesensitizationRuleController.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
api
.
controller
;
import
com.yd.common.result.Result
;
import
com.yd.communication.api.service.ApiCoDesensitizationRuleService
;
import
com.yd.communication.feign.client.ApiCoDesensitizationRuleFeignClient
;
import
com.yd.communication.feign.response.desensitization.ApiCoDesensitizationRuleResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.web.bind.annotation.*
;
import
javax.annotation.Resource
;
import
java.util.List
;
/**
* 脱敏信息
*
* @author zxm
* @since 2026-07-28
*/
@Slf4j
@RestController
@RequestMapping
(
"/desensitization"
)
@Validated
public
class
ApiCoDesensitizationRuleController
implements
ApiCoDesensitizationRuleFeignClient
{
@Resource
private
ApiCoDesensitizationRuleService
apiCoDesensitizationRuleService
;
/**
* 根据 ID 查询单条规则
* @param bizId
* @return
*/
@Override
public
Result
<
ApiCoDesensitizationRuleResponse
>
getByBizId
(
String
bizId
)
{
return
apiCoDesensitizationRuleService
.
getByBizId
(
bizId
);
}
/**
* 根据资源类型和资源ID获取生效的脱敏规则列表(供脱敏引擎调用)
* @param resourceType
* @param resourceId
* @return
*/
@Override
public
Result
<
List
<
ApiCoDesensitizationRuleResponse
>>
getEnabledRules
(
String
resourceType
,
String
resourceId
)
{
return
apiCoDesensitizationRuleService
.
getEnabledRules
(
resourceType
,
resourceType
);
}
}
\ No newline at end of file
yd-communication-api/src/main/java/com/yd/communication/api/controller/CoDesensitizationRuleController.java
deleted
100644 → 0
View file @
95df52a3
package
com
.
yd
.
communication
.
api
.
controller
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* <p>
* 协同-脱敏设置表(通用) 前端控制器
* </p>
*
* @author zxm
* @since 2026-07-28
*/
@RestController
@RequestMapping
(
"/coDesensitizationRule"
)
public
class
CoDesensitizationRuleController
{
}
yd-communication-api/src/main/java/com/yd/communication/api/service/ApiCoDesensitizationRuleService.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
api
.
service
;
import
com.yd.common.result.Result
;
import
com.yd.communication.feign.response.desensitization.ApiCoDesensitizationRuleResponse
;
import
java.util.List
;
public
interface
ApiCoDesensitizationRuleService
{
Result
<
ApiCoDesensitizationRuleResponse
>
getByBizId
(
String
bizId
);
Result
<
List
<
ApiCoDesensitizationRuleResponse
>>
getEnabledRules
(
String
resourceType
,
String
resourceId
);
}
yd-communication-api/src/main/java/com/yd/communication/api/service/impl/ApiCoDesensitizationRuleServiceImpl.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
api
.
service
.
impl
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.communication.api.service.ApiCoDesensitizationRuleService
;
import
com.yd.communication.feign.response.desensitization.ApiCoDesensitizationRuleResponse
;
import
com.yd.communication.service.model.CoDesensitizationRule
;
import
com.yd.communication.service.service.ICoDesensitizationRuleService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.stereotype.Service
;
import
javax.annotation.Resource
;
import
java.util.List
;
import
java.util.stream.Collectors
;
@Slf4j
@Service
public
class
ApiCoDesensitizationRuleServiceImpl
implements
ApiCoDesensitizationRuleService
{
@Resource
private
ICoDesensitizationRuleService
ruleService
;
/**
* 根据 ID 查询单条规则
* @param bizId
* @return
*/
@Override
public
Result
<
ApiCoDesensitizationRuleResponse
>
getByBizId
(
String
bizId
)
{
CoDesensitizationRule
rule
=
ruleService
.
lambdaQuery
()
.
eq
(
CoDesensitizationRule:
:
getRuleBizId
,
bizId
)
.
last
(
" limit 1 "
)
.
one
();
if
(
rule
==
null
)
{
throw
new
BusinessException
(
"脱敏信息不存在"
);
}
ApiCoDesensitizationRuleResponse
response
=
new
ApiCoDesensitizationRuleResponse
();
BeanUtils
.
copyProperties
(
rule
,
response
);
return
Result
.
success
(
response
);
}
/**
* 根据资源类型和资源ID获取生效的脱敏规则列表(供脱敏引擎调用)
* @param resourceType
* @param resourceId
* @return
*/
@Override
public
Result
<
List
<
ApiCoDesensitizationRuleResponse
>>
getEnabledRules
(
String
resourceType
,
String
resourceId
)
{
List
<
CoDesensitizationRule
>
rules
=
ruleService
.
getEnabledRulesByResource
(
resourceType
,
resourceId
);
if
(
CollectionUtils
.
isEmpty
(
rules
))
{
return
Result
.
success
();
}
List
<
ApiCoDesensitizationRuleResponse
>
responses
=
rules
.
stream
().
map
(
dto
->
{
ApiCoDesensitizationRuleResponse
response
=
new
ApiCoDesensitizationRuleResponse
();
BeanUtils
.
copyProperties
(
dto
,
response
);
return
response
;
}).
collect
(
Collectors
.
toList
());
return
Result
.
success
(
responses
);
}
}
yd-communication-api/src/main/java/com/yd/communication/api/service/impl/ApiCoSessionServiceImpl.java
View file @
655980ca
...
@@ -7,6 +7,7 @@ import com.yd.common.result.Result;
...
@@ -7,6 +7,7 @@ import com.yd.common.result.Result;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.common.utils.RedisUtil
;
import
com.yd.common.utils.RedisUtil
;
import
com.yd.communication.api.service.ApiCoSessionService
;
import
com.yd.communication.api.service.ApiCoSessionService
;
import
com.yd.communication.api.utils.ClientInfoUtils
;
import
com.yd.communication.feign.dto.RoomRedisInfoDTO
;
import
com.yd.communication.feign.dto.RoomRedisInfoDTO
;
import
com.yd.communication.feign.enums.CoSessionStatusEnum
;
import
com.yd.communication.feign.enums.CoSessionStatusEnum
;
import
com.yd.communication.feign.enums.ControlHolderTypeEnum
;
import
com.yd.communication.feign.enums.ControlHolderTypeEnum
;
...
@@ -20,6 +21,7 @@ import com.yd.communication.feign.response.CreateResponse;
...
@@ -20,6 +21,7 @@ import com.yd.communication.feign.response.CreateResponse;
import
com.yd.communication.feign.response.JoinResponse
;
import
com.yd.communication.feign.response.JoinResponse
;
import
com.yd.communication.feign.response.SessionDetailResponse
;
import
com.yd.communication.feign.response.SessionDetailResponse
;
import
com.yd.communication.service.model.CoSession
;
import
com.yd.communication.service.model.CoSession
;
import
com.yd.communication.service.service.ICoOperationLogService
;
import
com.yd.communication.service.service.ICoSessionService
;
import
com.yd.communication.service.service.ICoSessionService
;
import
com.yd.communication.service.service.IRecordingTaskService
;
import
com.yd.communication.service.service.IRecordingTaskService
;
import
com.yd.communication.service.utils.RandomUtil
;
import
com.yd.communication.service.utils.RandomUtil
;
...
@@ -28,7 +30,6 @@ import org.apache.commons.lang3.StringUtils;
...
@@ -28,7 +30,6 @@ import org.apache.commons.lang3.StringUtils;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.annotation.Transactional
;
import
javax.annotation.Resource
;
import
javax.annotation.Resource
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.util.UUID
;
import
java.util.UUID
;
...
@@ -44,6 +45,9 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
...
@@ -44,6 +45,9 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
private
IRecordingTaskService
recordingService
;
private
IRecordingTaskService
recordingService
;
@Resource
@Resource
private
ICoOperationLogService
operationLogService
;
@Resource
private
RedisUtil
redisUtil
;
private
RedisUtil
redisUtil
;
/**
/**
...
@@ -138,8 +142,19 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
...
@@ -138,8 +142,19 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
// recordingService.startRecording(session.getCoSessionBizId(), roomId);
// recordingService.startRecording(session.getCoSessionBizId(), roomId);
log
.
info
(
"【创建会话-内部】自动录制已触发(未实际启动)"
);
log
.
info
(
"【创建会话-内部】自动录制已触发(未实际启动)"
);
}
}
log
.
info
(
"【创建会话-内部】创建成功, roomId={}, roomPwd={}"
,
roomId
,
roomPwd
);
log
.
info
(
"【创建会话-内部】创建成功, roomId={}, roomPwd={}"
,
roomId
,
roomPwd
);
//生成协同操作日志
operationLogService
.
log
(
session
.
getCoSessionBizId
(),
ownerId
,
ownerType
,
ownerId
,
"create_session"
,
String
.
format
(
"创建会话 roomId=%s, roomPwd=%s"
,
session
.
getRoomId
(),
session
.
getRoomPwd
()),
ClientInfoUtils
.
getDevice
(),
ClientInfoUtils
.
getClientIp
()
);
return
session
;
return
session
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"【创建会话-内部】异常"
,
e
);
log
.
error
(
"【创建会话-内部】异常"
,
e
);
...
@@ -257,6 +272,17 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
...
@@ -257,6 +272,17 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
log
.
warn
(
"【加入会话-内部】Redis缓存不存在,可能已过期,roomId={}"
,
session
.
getRoomId
());
log
.
warn
(
"【加入会话-内部】Redis缓存不存在,可能已过期,roomId={}"
,
session
.
getRoomId
());
}
}
//生成协同操作日志
operationLogService
.
log
(
session
.
getCoSessionBizId
(),
participantId
,
participantType
,
participantId
,
"join_session"
,
String
.
format
(
"加入会话 roomId=%s, 控制权转移至%s"
,
session
.
getRoomId
(),
session
.
getControlHolderType
()),
ClientInfoUtils
.
getDevice
(),
ClientInfoUtils
.
getClientIp
()
);
return
session
;
return
session
;
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"【加入会话-内部】异常"
,
e
);
log
.
error
(
"【加入会话-内部】异常"
,
e
);
...
@@ -314,9 +340,17 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
...
@@ -314,9 +340,17 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
redisUtil
.
deleteObject
(
RedisEnum
.
ROOM
.
getPrefix
()
+
coSession
.
getRoomId
());
redisUtil
.
deleteObject
(
RedisEnum
.
ROOM
.
getPrefix
()
+
coSession
.
getRoomId
());
log
.
info
(
"【结束会话】Redis缓存已删除"
);
log
.
info
(
"【结束会话】Redis缓存已删除"
);
// 结束录制视频,并且更新录制任务表信息存档 TODO
// 添加操作日志,协同-操作日志表
operationLogService
.
log
(
// 添加操作日志,协同-操作日志表 TODO
coSession
.
getCoSessionBizId
(),
null
,
null
,
null
,
"end_session"
,
String
.
format
(
"结束会话 roomId=%s"
,
coSession
.
getRoomId
()),
ClientInfoUtils
.
getDevice
(),
ClientInfoUtils
.
getClientIp
()
);
CommonResponse
response
=
new
CommonResponse
();
CommonResponse
response
=
new
CommonResponse
();
response
.
setMessage
(
"会话已结束"
);
response
.
setMessage
(
"会话已结束"
);
...
@@ -395,7 +429,17 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
...
@@ -395,7 +429,17 @@ public class ApiCoSessionServiceImpl implements ApiCoSessionService {
}
else
{
}
else
{
log
.
warn
(
"【切换控制权-内部】Redis缓存不存在,可能已过期"
);
log
.
warn
(
"【切换控制权-内部】Redis缓存不存在,可能已过期"
);
}
}
// 添加操作日志,协同-操作日志表 TODO
// 添加操作日志,协同-操作日志表
operationLogService
.
log
(
session
.
getCoSessionBizId
(),
session
.
getParticipantId
(),
ControlHolderTypeEnum
.
PARTICIPANT
.
getItemValue
(),
session
.
getParticipantId
(),
"transfer_control"
,
String
.
format
(
"切换控制权至 %s:%s"
,
session
.
getControlHolderType
(),
session
.
getControlHolderId
()),
ClientInfoUtils
.
getDevice
(),
ClientInfoUtils
.
getClientIp
()
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"【切换控制权-内部】异常"
,
e
);
log
.
error
(
"【切换控制权-内部】异常"
,
e
);
throw
e
;
throw
e
;
...
...
yd-communication-api/src/main/java/com/yd/communication/api/service/impl/ApiRecordingTaskServiceImpl.java
View file @
655980ca
...
@@ -3,15 +3,15 @@ package com.yd.communication.api.service.impl;
...
@@ -3,15 +3,15 @@ package com.yd.communication.api.service.impl;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.enums.ProjectEnum
;
import
com.yd.common.enums.TenantEnum
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.result.Result
;
import
com.yd.common.result.Result
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.communication.api.service.ApiRecordingTaskService
;
import
com.yd.communication.api.service.ApiRecordingTaskService
;
import
com.yd.communication.api.utils.ClientInfoUtils
;
import
com.yd.communication.feign.request.recording.ApiStartRecordingRequest
;
import
com.yd.communication.feign.request.recording.ApiStartRecordingRequest
;
import
com.yd.communication.feign.response.recording.ApiQueryRecordingResponse
;
import
com.yd.communication.feign.response.recording.ApiQueryRecordingResponse
;
import
com.yd.communication.service.model.RecordingTask
;
import
com.yd.communication.service.model.RecordingTask
;
import
com.yd.communication.service.service.ICoOperationLogService
;
import
com.yd.communication.service.service.IRecordingTaskService
;
import
com.yd.communication.service.service.IRecordingTaskService
;
import
com.yd.oss.feign.client.ApiOssFeignClient
;
import
com.yd.oss.feign.client.ApiOssFeignClient
;
import
com.yd.oss.feign.request.ApiUploadFileRequest
;
import
com.yd.oss.feign.request.ApiUploadFileRequest
;
...
@@ -39,6 +39,9 @@ public class ApiRecordingTaskServiceImpl implements ApiRecordingTaskService {
...
@@ -39,6 +39,9 @@ public class ApiRecordingTaskServiceImpl implements ApiRecordingTaskService {
private
ApiOssFeignClient
apiOssFeignClient
;
private
ApiOssFeignClient
apiOssFeignClient
;
@Resource
@Resource
private
ICoOperationLogService
operationLogService
;
@Resource
private
ObjectMapper
objectMapper
;
// 注入 Jackson ObjectMapper
private
ObjectMapper
objectMapper
;
// 注入 Jackson ObjectMapper
/**
/**
...
@@ -74,6 +77,18 @@ public class ApiRecordingTaskServiceImpl implements ApiRecordingTaskService {
...
@@ -74,6 +77,18 @@ public class ApiRecordingTaskServiceImpl implements ApiRecordingTaskService {
iRecordingTaskService
.
save
(
task
);
iRecordingTaskService
.
save
(
task
);
log
.
info
(
"录制任务创建成功,taskId={}"
,
task
.
getTaskId
());
log
.
info
(
"录制任务创建成功,taskId={}"
,
task
.
getTaskId
());
//生成协同操作日志
operationLogService
.
log
(
request
.
getBizId
(),
"system"
,
"system"
,
"system"
,
"start_recording"
,
String
.
format
(
"开始录制 taskId=%s, bizType=%s"
,
task
.
getTaskId
(),
request
.
getBizType
()),
ClientInfoUtils
.
getDevice
(),
ClientInfoUtils
.
getClientIp
()
);
return
Result
.
success
(
task
.
getTaskId
());
return
Result
.
success
(
task
.
getTaskId
());
}
}
...
@@ -142,6 +157,18 @@ public class ApiRecordingTaskServiceImpl implements ApiRecordingTaskService {
...
@@ -142,6 +157,18 @@ public class ApiRecordingTaskServiceImpl implements ApiRecordingTaskService {
result
.
put
(
"fileKey"
,
uploadResponse
.
getFileKey
());
result
.
put
(
"fileKey"
,
uploadResponse
.
getFileKey
());
log
.
info
(
"录制文件上传成功,fileUrl={}"
,
task
.
getFileUrl
());
log
.
info
(
"录制文件上传成功,fileUrl={}"
,
task
.
getFileUrl
());
//生成协同操作日志
operationLogService
.
log
(
task
.
getBizId
(),
"system"
,
"system"
,
"system"
,
"stop_recording"
,
String
.
format
(
"停止录制 taskId=%s, fileUrl=%s"
,
task
.
getTaskId
(),
task
.
getFileUrl
()),
ClientInfoUtils
.
getDevice
(),
ClientInfoUtils
.
getClientIp
()
);
return
Result
.
success
(
result
);
return
Result
.
success
(
result
);
}
}
...
...
yd-communication-api/src/main/java/com/yd/communication/api/utils/ClientInfoUtils.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
api
.
utils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
javax.servlet.http.HttpServletRequest
;
/**
* 客户端信息工具类(IP、设备号等)
* 优先从 HTTP 请求获取,若不存在则从 IpContextHolder 获取(WebSocket 场景)
*
* @author zxm
* @date 2026-08-03
*/
public
class
ClientInfoUtils
{
/**
* 获取客户端真实 IP
* 优先级:X-Forwarded-For > X-Real-IP > RemoteAddr > IpContextHolder
*
* @return 客户端 IP
*/
public
static
String
getClientIp
()
{
// 1. 从 HTTP 请求获取
try
{
ServletRequestAttributes
attributes
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
if
(
attributes
!=
null
)
{
HttpServletRequest
request
=
attributes
.
getRequest
();
if
(
request
!=
null
)
{
// 获取 X-Forwarded-For(经过代理时)
String
ip
=
request
.
getHeader
(
"X-Forwarded-For"
);
if
(
StringUtils
.
isBlank
(
ip
))
{
ip
=
request
.
getHeader
(
"X-Real-IP"
);
}
if
(
StringUtils
.
isBlank
(
ip
))
{
ip
=
request
.
getRemoteAddr
();
}
// X-Forwarded-For 可能包含多个 IP,取第一个
if
(
StringUtils
.
isNotBlank
(
ip
)
&&
ip
.
contains
(
","
))
{
ip
=
ip
.
split
(
","
)[
0
].
trim
();
}
if
(
StringUtils
.
isNotBlank
(
ip
))
{
return
ip
;
}
}
}
}
catch
(
Exception
e
)
{
// 忽略异常,继续回退
}
// 2. 回退到 IpContextHolder(WebSocket 场景由 CoWebSocketServer 设置)
return
IpContextHolder
.
getIp
();
}
/**
* 获取设备号(User-Agent)
* 优先级:HTTP 请求头 > IpContextHolder
*
* @return 设备号(User-Agent)
*/
public
static
String
getDevice
()
{
try
{
ServletRequestAttributes
attributes
=
(
ServletRequestAttributes
)
RequestContextHolder
.
getRequestAttributes
();
if
(
attributes
!=
null
)
{
HttpServletRequest
request
=
attributes
.
getRequest
();
if
(
request
!=
null
)
{
return
request
.
getHeader
(
"User-Agent"
);
}
}
}
catch
(
Exception
e
)
{
// 忽略异常
}
return
IpContextHolder
.
getDevice
();
}
/**
* 获取完整客户端信息(IP + 设备)
* @return 格式:IP | User-Agent
*/
public
static
String
getClientInfo
()
{
return
getClientIp
()
+
" | "
+
getDevice
();
}
}
\ No newline at end of file
yd-communication-api/src/main/java/com/yd/communication/api/utils/IpContextHolder.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
api
.
utils
;
/**
* 用于在 WebSocket 等非 HTTP 环境下传递客户端 IP 和设备信息
* <p>
* 使用 ThreadLocal 存储,避免参数透传,确保线程安全。
* 通常在 WebSocket 的 @OnMessage 方法中设置,在业务 Service 中获取,
* 并在 finally 块中清除,防止内存泄漏。
* </p>
*
* @author zxm
* @date 2026-08-03
*/
public
class
IpContextHolder
{
private
static
final
ThreadLocal
<
String
>
IP_HOLDER
=
new
ThreadLocal
<>();
private
static
final
ThreadLocal
<
String
>
DEVICE_HOLDER
=
new
ThreadLocal
<>();
/**
* 设置当前线程的客户端 IP
*/
public
static
void
setIp
(
String
ip
)
{
IP_HOLDER
.
set
(
ip
);
}
/**
* 获取当前线程的客户端 IP
*/
public
static
String
getIp
()
{
return
IP_HOLDER
.
get
();
}
/**
* 设置当前线程的设备号(User-Agent 等)
*/
public
static
void
setDevice
(
String
device
)
{
DEVICE_HOLDER
.
set
(
device
);
}
/**
* 获取当前线程的设备号
*/
public
static
String
getDevice
()
{
return
DEVICE_HOLDER
.
get
();
}
/**
* 清除当前线程的上下文(防止内存泄漏)
*/
public
static
void
clear
()
{
IP_HOLDER
.
remove
();
DEVICE_HOLDER
.
remove
();
}
}
\ No newline at end of file
yd-communication-api/src/main/java/com/yd/communication/api/websocket/CoWebSocketServer.java
View file @
655980ca
...
@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON;
...
@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.yd.communication.api.service.ApiCoSessionService
;
import
com.yd.communication.api.service.ApiCoSessionService
;
import
com.yd.communication.api.utils.IpContextHolder
;
import
com.yd.communication.feign.dto.RoomRedisInfoDTO
;
import
com.yd.communication.feign.dto.RoomRedisInfoDTO
;
import
com.yd.communication.feign.enums.ControlHolderTypeEnum
;
import
com.yd.communication.feign.enums.ControlHolderTypeEnum
;
import
com.yd.communication.feign.request.EndSessionRequest
;
import
com.yd.communication.feign.request.EndSessionRequest
;
...
@@ -23,13 +24,14 @@ import javax.websocket.*;
...
@@ -23,13 +24,14 @@ import javax.websocket.*;
import
javax.websocket.server.PathParam
;
import
javax.websocket.server.PathParam
;
import
javax.websocket.server.ServerEndpoint
;
import
javax.websocket.server.ServerEndpoint
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.lang.reflect.Method
;
import
java.net.InetSocketAddress
;
import
java.net.URLDecoder
;
import
java.net.URLDecoder
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.util.*
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.CopyOnWriteArraySet
;
import
java.util.concurrent.CopyOnWriteArraySet
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
org.springframework.data.redis.connection.RedisConnection
;
/**
/**
* 协同 WebSocket 服务端(支持多节点部署)
* 协同 WebSocket 服务端(支持多节点部署)
...
@@ -513,6 +515,11 @@ public class CoWebSocketServer {
...
@@ -513,6 +515,11 @@ public class CoWebSocketServer {
*/
*/
@OnMessage
@OnMessage
public
void
onMessage
(
Session
session
,
String
message
)
{
public
void
onMessage
(
Session
session
,
String
message
)
{
// 获取 IP
String
remoteIp
=
getClientIp
(
session
);
IpContextHolder
.
setIp
(
remoteIp
);
IpContextHolder
.
setDevice
(
null
);
// 根据会话查询对应的房间号
// 根据会话查询对应的房间号
String
roomId
=
SESSION_ROOM
.
get
(
session
);
String
roomId
=
SESSION_ROOM
.
get
(
session
);
if
(
roomId
==
null
)
{
if
(
roomId
==
null
)
{
...
@@ -592,7 +599,7 @@ public class CoWebSocketServer {
...
@@ -592,7 +599,7 @@ public class CoWebSocketServer {
// 记录操作日志(用于合规审计)
// 记录操作日志(用于合规审计)
if
(
bizId
!=
null
)
{
if
(
bizId
!=
null
)
{
operationLogService
.
log
(
bizId
,
userId
,
userType
,
userId
,
action
,
correctMsg
,
null
,
null
);
operationLogService
.
log
(
bizId
,
userId
,
userType
,
userId
,
action
,
correctMsg
,
IpContextHolder
.
getDevice
(),
IpContextHolder
.
getIp
()
);
}
}
log
.
info
(
"控制权切换成功: roomId={}, holder={}:{}"
,
roomId
,
correctHolderType
,
correctHolderId
);
log
.
info
(
"控制权切换成功: roomId={}, holder={}:{}"
,
roomId
,
correctHolderType
,
correctHolderId
);
...
@@ -627,6 +634,19 @@ public class CoWebSocketServer {
...
@@ -627,6 +634,19 @@ public class CoWebSocketServer {
// 关闭房间所有连接并清理资源
// 关闭房间所有连接并清理资源
closeRoom
(
roomId
);
closeRoom
(
roomId
);
log
.
info
(
"共享已结束: roomId={}"
,
roomId
);
log
.
info
(
"共享已结束: roomId={}"
,
roomId
);
if
(
bizId
!=
null
)
{
operationLogService
.
log
(
bizId
,
userId
,
userType
,
userId
,
"end_sharing"
,
"结束共享"
,
IpContextHolder
.
getDevice
(),
IpContextHolder
.
getIp
()
);
}
return
;
return
;
}
}
...
@@ -639,7 +659,7 @@ public class CoWebSocketServer {
...
@@ -639,7 +659,7 @@ public class CoWebSocketServer {
// 记录操作日志
// 记录操作日志
if
(
bizId
!=
null
)
{
if
(
bizId
!=
null
)
{
operationLogService
.
log
(
bizId
,
userId
,
userType
,
userId
,
action
,
message
,
null
,
null
);
operationLogService
.
log
(
bizId
,
userId
,
userType
,
userId
,
action
,
message
,
IpContextHolder
.
getDevice
(),
IpContextHolder
.
getIp
()
);
}
}
return
;
return
;
}
}
...
@@ -686,7 +706,7 @@ public class CoWebSocketServer {
...
@@ -686,7 +706,7 @@ public class CoWebSocketServer {
// 4.5 记录操作日志(合规审计)
// 4.5 记录操作日志(合规审计)
if
(
bizId
!=
null
)
{
if
(
bizId
!=
null
)
{
operationLogService
.
log
(
bizId
,
userId
,
userType
,
userId
,
action
,
message
,
null
,
null
);
operationLogService
.
log
(
bizId
,
userId
,
userType
,
userId
,
action
,
message
,
IpContextHolder
.
getDevice
(),
IpContextHolder
.
getIp
()
);
}
}
return
;
return
;
}
}
...
@@ -698,6 +718,9 @@ public class CoWebSocketServer {
...
@@ -698,6 +718,9 @@ public class CoWebSocketServer {
// 处理消息异常,向客户端返回错误信息
// 处理消息异常,向客户端返回错误信息
log
.
error
(
"处理WebSocket消息异常,消息内容: {}"
,
message
,
e
);
log
.
error
(
"处理WebSocket消息异常,消息内容: {}"
,
message
,
e
);
sendError
(
session
,
"服务器处理异常"
);
sendError
(
session
,
"服务器处理异常"
);
}
finally
{
//清除上下文,防止内存泄漏
IpContextHolder
.
clear
();
}
}
}
}
...
@@ -877,4 +900,40 @@ public class CoWebSocketServer {
...
@@ -877,4 +900,40 @@ public class CoWebSocketServer {
return
value
;
return
value
;
}
}
}
}
// ==================== 获取客户端 IP 的工具方法 ====================
/**
* 获取客户端 IP(由于 javax.websocket.Session 接口没有 getRemoteAddress,通过反射调用)
*/
private
String
getClientIp
(
Session
session
)
{
try
{
// 尝试直接通过反射调用 getRemoteAddress(Tomcat 等实现类有该方法)
Method
method
=
session
.
getClass
().
getMethod
(
"getRemoteAddress"
);
Object
result
=
method
.
invoke
(
session
);
if
(
result
instanceof
InetSocketAddress
)
{
InetSocketAddress
address
=
(
InetSocketAddress
)
result
;
return
address
.
getAddress
().
getHostAddress
();
}
}
catch
(
Exception
e
)
{
log
.
debug
(
"通过反射获取 getRemoteAddress 失败,尝试其他方式"
);
}
// 备选:从请求参数中获取(前端可传 ?ip=xxx)
Map
<
String
,
List
<
String
>>
params
=
session
.
getRequestParameterMap
();
if
(
params
!=
null
&&
params
.
containsKey
(
"ip"
))
{
List
<
String
>
ips
=
params
.
get
(
"ip"
);
if
(
ips
!=
null
&&
!
ips
.
isEmpty
())
{
return
ips
.
get
(
0
);
}
}
// 再备选:从 getUserProperties 中获取(如由 configurator 存储)
Object
storedIp
=
session
.
getUserProperties
().
get
(
"remoteIp"
);
if
(
storedIp
!=
null
)
{
return
storedIp
.
toString
();
}
return
"unknown"
;
}
}
}
\ No newline at end of file
yd-communication-feign/src/main/java/com/yd/communication/feign/client/ApiCoDesensitizationRuleFeignClient.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
feign
.
client
;
import
com.yd.common.result.Result
;
import
com.yd.communication.feign.fallback.ApiCoDesensitizationRuleFeignFallbackFactory
;
import
com.yd.communication.feign.response.desensitization.ApiCoDesensitizationRuleResponse
;
import
org.springframework.cloud.openfeign.FeignClient
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
javax.validation.constraints.NotBlank
;
import
java.util.List
;
/**
* 通信服务-脱敏信息Feign 客户端
*
* @author zxm
* @date 2026-07-28
*/
@FeignClient
(
name
=
"yd-communication-api"
,
path
=
"/communication/api/desensitization"
,
fallbackFactory
=
ApiCoDesensitizationRuleFeignFallbackFactory
.
class
)
public
interface
ApiCoDesensitizationRuleFeignClient
{
/**
* 根据业务ID查询单条规则
*/
@GetMapping
(
"/{bizId}"
)
Result
<
ApiCoDesensitizationRuleResponse
>
getByBizId
(
@PathVariable
@NotBlank
(
message
=
"业务ID不能为空"
)
String
bizId
);
/**
* 根据资源类型和资源ID获取生效的脱敏规则列表(供脱敏引擎调用)
*/
@GetMapping
(
"/enabled"
)
Result
<
List
<
ApiCoDesensitizationRuleResponse
>>
getEnabledRules
(
@RequestParam
(
value
=
"resourceType"
,
required
=
false
)
String
resourceType
,
@RequestParam
(
value
=
"resourceId"
,
required
=
false
)
String
resourceId
);
}
yd-communication-feign/src/main/java/com/yd/communication/feign/fallback/ApiCoDesensitizationRuleFeignFallbackFactory.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
feign
.
fallback
;
import
com.yd.common.result.Result
;
import
com.yd.communication.feign.client.ApiCoDesensitizationRuleFeignClient
;
import
com.yd.communication.feign.response.desensitization.ApiCoDesensitizationRuleResponse
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.cloud.openfeign.FallbackFactory
;
import
org.springframework.stereotype.Component
;
import
java.util.List
;
/**
* 通信服务-脱敏信息Feign降级处理
*/
@Slf4j
@Component
public
class
ApiCoDesensitizationRuleFeignFallbackFactory
implements
FallbackFactory
<
ApiCoDesensitizationRuleFeignClient
>
{
@Override
public
ApiCoDesensitizationRuleFeignClient
create
(
Throwable
cause
)
{
return
new
ApiCoDesensitizationRuleFeignClient
()
{
@Override
public
Result
<
ApiCoDesensitizationRuleResponse
>
getByBizId
(
String
bizId
)
{
return
null
;
}
@Override
public
Result
<
List
<
ApiCoDesensitizationRuleResponse
>>
getEnabledRules
(
String
resourceType
,
String
resourceId
)
{
return
null
;
}
};
}
}
yd-communication-feign/src/main/java/com/yd/communication/feign/response/desensitization/ApiCoDesensitizationRuleResponse.java
0 → 100644
View file @
655980ca
package
com
.
yd
.
communication
.
feign
.
response
.
desensitization
;
import
lombok.Data
;
@Data
public
class
ApiCoDesensitizationRuleResponse
{
/**
* 主键
*/
private
Long
id
;
/**
* 脱敏规则唯一业务ID
*/
private
String
ruleBizId
;
/**
* 规则名称(如:报告-客户姓名脱敏)
*/
private
String
ruleName
;
/**
* 资源类型:report/news/mini_program
*/
private
String
resourceType
;
/**
* 资源业务ID(NULL表示全局规则,适用于该类型下所有资源)
*/
private
String
resourceId
;
/**
* 脱敏字段路径(JSON Path,如:$.customer.name)
*/
private
String
fieldPath
;
/**
* 字段显示名称(冗余,便于运营配置)
*/
private
String
fieldName
;
/**
* 脱敏方式:mask-掩码(如:张**)、hide-完全隐藏(****)、replace-替换(***)、partial-部分显示(如:138****8000)
*/
private
String
maskType
;
/**
* 脱敏配置JSON(如:{"prefix":1,"suffix":1,"replace_char":"*"})
*/
private
String
maskConfig
;
/**
* 规则是否启用:0-停用,1-启用
*/
private
Integer
enabled
;
/**
* 是否为默认规则:0-否,1-是(资源未配置时使用默认)
*/
private
Integer
isDefault
;
/**
* 排序顺序
*/
private
Integer
sortOrder
;
}
yd-communication-service/src/main/java/com/yd/communication/service/service/ICoDesensitizationRuleService.java
View file @
655980ca
package
com
.
yd
.
communication
.
service
.
service
;
package
com
.
yd
.
communication
.
service
.
service
;
import
com.yd.communication.service.model.CoDesensitizationRule
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.yd.communication.service.model.CoDesensitizationRule
;
import
java.util.List
;
/**
/**
* <p>
* 协同-脱敏设置表 服务类
* 协同-脱敏设置表(通用) 服务类
* </p>
*
* @author zxm
* @since 2026-07-28
*/
*/
public
interface
ICoDesensitizationRuleService
extends
IService
<
CoDesensitizationRule
>
{
public
interface
ICoDesensitizationRuleService
extends
IService
<
CoDesensitizationRule
>
{
}
/**
* 分页查询脱敏规则列表
*/
IPage
<
CoDesensitizationRule
>
pageList
(
Page
<
CoDesensitizationRule
>
page
,
String
resourceType
,
String
resourceId
,
Integer
enabled
);
/**
* 根据资源类型和资源ID获取生效的脱敏规则列表
*/
List
<
CoDesensitizationRule
>
getEnabledRulesByResource
(
String
resourceType
,
String
resourceId
);
/**
* 启用/停用规则
*/
void
toggleEnabled
(
Long
id
,
Integer
enabled
);
/**
* 逻辑删除规则
*/
void
deleteById
(
Long
id
);
}
\ No newline at end of file
yd-communication-service/src/main/java/com/yd/communication/service/service/impl/CoDesensitizationRuleServiceImpl.java
View file @
655980ca
package
com
.
yd
.
communication
.
service
.
service
.
impl
;
package
com
.
yd
.
communication
.
service
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.yd.communication.service.model.CoDesensitizationRule
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.yd.common.enums.CommonEnum
;
import
com.yd.common.exception.BusinessException
;
import
com.yd.common.utils.RandomStringGenerator
;
import
com.yd.communication.service.dao.CoDesensitizationRuleMapper
;
import
com.yd.communication.service.dao.CoDesensitizationRuleMapper
;
import
com.yd.communication.service.model.CoDesensitizationRule
;
import
com.yd.communication.service.service.ICoDesensitizationRuleService
;
import
com.yd.communication.service.service.ICoDesensitizationRuleService
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.
springframework.beans.factory.annotation.Autowired
;
import
org.
apache.commons.lang3.StringUtils
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java
x.annotation.Resourc
e
;
import
java
.time.LocalDateTim
e
;
import
java.util.List
;
import
java.util.List
;
/**
* <p>
* 协同-脱敏设置表(通用) 服务实现类
* </p>
*
* @author zxm
* @since 2026-07-28
*/
@Slf4j
@Slf4j
@Service
@Service
public
class
CoDesensitizationRuleServiceImpl
extends
ServiceImpl
<
CoDesensitizationRuleMapper
,
CoDesensitizationRule
>
implements
ICoDesensitizationRuleService
{
public
class
CoDesensitizationRuleServiceImpl
extends
ServiceImpl
<
CoDesensitizationRuleMapper
,
CoDesensitizationRule
>
@Resource
implements
ICoDesensitizationRuleService
{
private
CoDesensitizationRuleMapper
ruleMapper
;
private
final
ObjectMapper
objectMapper
=
new
ObjectMapper
();
@Override
public
IPage
<
CoDesensitizationRule
>
pageList
(
Page
<
CoDesensitizationRule
>
page
,
String
resourceType
,
String
resourceId
,
Integer
enabled
)
{
LambdaQueryWrapper
<
CoDesensitizationRule
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
eq
(
CoDesensitizationRule:
:
getIsDeleted
,
0
);
if
(
StringUtils
.
isNotBlank
(
resourceType
))
{
wrapper
.
eq
(
CoDesensitizationRule:
:
getResourceType
,
resourceType
);
}
if
(
StringUtils
.
isNotBlank
(
resourceId
))
{
wrapper
.
eq
(
CoDesensitizationRule:
:
getResourceId
,
resourceId
);
}
if
(
enabled
!=
null
)
{
wrapper
.
eq
(
CoDesensitizationRule:
:
getEnabled
,
enabled
);
}
wrapper
.
orderByAsc
(
CoDesensitizationRule:
:
getSortOrder
)
.
orderByDesc
(
CoDesensitizationRule:
:
getCreateTime
);
return
this
.
page
(
page
,
wrapper
);
}
public
String
applyDesensitization
(
String
rawData
,
String
resourceType
,
String
resourceId
)
{
@Override
// 获取规则(先特定资源,再默认)
public
List
<
CoDesensitizationRule
>
getEnabledRulesByResource
(
String
resourceType
,
String
resourceId
)
{
LambdaQueryWrapper
<
CoDesensitizationRule
>
wrapper
=
new
LambdaQueryWrapper
<>();
LambdaQueryWrapper
<
CoDesensitizationRule
>
wrapper
=
new
LambdaQueryWrapper
<>();
wrapper
.
eq
(
CoDesensitizationRule:
:
get
ResourceType
,
resourceType
)
wrapper
.
eq
(
CoDesensitizationRule:
:
get
IsDeleted
,
0
)
.
eq
(
CoDesensitizationRule:
:
getEnabled
,
1
)
.
eq
(
CoDesensitizationRule:
:
getEnabled
,
1
)
.
eq
(
StringUtils
.
isNotBlank
(
resourceType
),
CoDesensitizationRule:
:
getResourceType
,
resourceType
)
.
eq
(
StringUtils
.
isNotBlank
(
resourceId
),
CoDesensitizationRule:
:
getResourceId
,
resourceId
)
.
orderByAsc
(
CoDesensitizationRule:
:
getSortOrder
);
.
orderByAsc
(
CoDesensitizationRule:
:
getSortOrder
);
return
this
.
list
(
wrapper
);
}
List
<
CoDesensitizationRule
>
rules
;
@Override
// 先查特定资源
@Transactional
(
rollbackFor
=
Exception
.
class
)
wrapper
.
eq
(
CoDesensitizationRule:
:
getResourceId
,
resourceId
);
public
void
toggleEnabled
(
Long
id
,
Integer
enabled
)
{
rules
=
ruleMapper
.
selectList
(
wrapper
);
CoDesensitizationRule
rule
=
this
.
getById
(
id
);
if
(
rules
.
isEmpty
())
{
if
(
rule
==
null
||
rule
.
getIsDeleted
()
==
1
)
{
// 查默认规则
throw
new
BusinessException
(
"规则不存在或已删除"
);
wrapper
.
clear
();
wrapper
.
eq
(
CoDesensitizationRule:
:
getResourceType
,
resourceType
)
.
eq
(
CoDesensitizationRule:
:
getIsDefault
,
1
)
.
eq
(
CoDesensitizationRule:
:
getEnabled
,
1
)
.
orderByAsc
(
CoDesensitizationRule:
:
getSortOrder
);
rules
=
ruleMapper
.
selectList
(
wrapper
);
}
if
(
rules
.
isEmpty
())
{
return
rawData
;
}
}
rule
.
setEnabled
(
enabled
);
rule
.
setUpdaterId
(
"system"
);
rule
.
setUpdateTime
(
LocalDateTime
.
now
());
this
.
updateById
(
rule
);
log
.
info
(
"脱敏规则 {} 状态已切换为: {}"
,
id
,
enabled
==
1
?
"启用"
:
"停用"
);
}
try
{
@Override
JsonNode
root
=
objectMapper
.
readTree
(
rawData
);
@Transactional
(
rollbackFor
=
Exception
.
class
)
for
(
CoDesensitizationRule
rule
:
rules
)
{
public
void
deleteById
(
Long
id
)
{
String
fieldPath
=
rule
.
getFieldPath
();
CoDesensitizationRule
rule
=
this
.
getById
(
id
);
// 简单处理:假设路径是$.xxx,直接取字段
if
(
rule
==
null
||
rule
.
getIsDeleted
()
==
1
)
{
String
fieldName
=
fieldPath
.
replace
(
"$."
,
""
);
throw
new
BusinessException
(
"规则不存在或已删除"
);
if
(
root
.
has
(
fieldName
))
{
String
original
=
root
.
get
(
fieldName
).
asText
();
String
masked
=
maskValue
(
original
,
rule
.
getMaskType
(),
rule
.
getMaskConfig
());
// 由于JsonNode不可变,简单返回,生产需构建新节点
}
}
return
objectMapper
.
writeValueAsString
(
root
);
}
catch
(
Exception
e
)
{
log
.
error
(
"脱敏失败"
,
e
);
return
rawData
;
}
}
rule
.
setIsDeleted
(
1
);
rule
.
setUpdaterId
(
"system"
);
rule
.
setUpdateTime
(
LocalDateTime
.
now
());
this
.
updateById
(
rule
);
log
.
info
(
"脱敏规则 {} 已逻辑删除"
,
id
);
}
}
private
String
maskValue
(
String
original
,
String
maskType
,
String
maskConfig
)
{
/**
try
{
* 保存或更新前的公共逻辑
JsonNode
config
=
objectMapper
.
readTree
(
maskConfig
!=
null
?
maskConfig
:
"{}"
);
*/
int
prefix
=
config
.
has
(
"prefix"
)
?
config
.
get
(
"prefix"
).
asInt
()
:
0
;
@Override
int
suffix
=
config
.
has
(
"suffix"
)
?
config
.
get
(
"suffix"
).
asInt
()
:
0
;
@Transactional
(
rollbackFor
=
Exception
.
class
)
String
replaceChar
=
config
.
has
(
"replace_char"
)
?
config
.
get
(
"replace_char"
).
asText
()
:
"*"
;
public
boolean
saveOrUpdate
(
CoDesensitizationRule
entity
)
{
if
(
entity
==
null
)
{
switch
(
maskType
)
{
return
false
;
case
"mask"
:
}
case
"partial"
:
if
(
entity
.
getId
()
==
null
)
{
if
(
original
.
length
()
<=
prefix
+
suffix
)
return
original
;
// 新增
int
middle
=
original
.
length
()
-
prefix
-
suffix
;
entity
.
setRuleBizId
(
RandomStringGenerator
.
generateBizId16
(
CommonEnum
.
UID_TYPE_DESENSITIZATION_RULE
.
getCode
()));
return
original
.
substring
(
0
,
prefix
)
+
entity
.
setIsDeleted
(
0
);
// replaceChar.repeat(middle) +
entity
.
setCreateTime
(
LocalDateTime
.
now
());
original
.
substring
(
original
.
length
()
-
suffix
);
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
case
"hide"
:
if
(
StringUtils
.
isBlank
(
entity
.
getCreatorId
()))
{
return
"****"
;
entity
.
setCreatorId
(
"system"
);
case
"replace"
:
}
return
config
.
has
(
"replace_char"
)
?
config
.
get
(
"replace_char"
).
asText
()
:
"***"
;
if
(
StringUtils
.
isBlank
(
entity
.
getUpdaterId
()))
{
default
:
entity
.
setUpdaterId
(
"system"
);
return
original
;
}
// 默认启用
if
(
entity
.
getEnabled
()
==
null
)
{
entity
.
setEnabled
(
1
);
}
}
else
{
// 更新
CoDesensitizationRule
exist
=
this
.
getById
(
entity
.
getId
());
if
(
exist
==
null
||
exist
.
getIsDeleted
()
==
1
)
{
throw
new
BusinessException
(
"规则不存在或已删除"
);
}
entity
.
setUpdateTime
(
LocalDateTime
.
now
());
if
(
StringUtils
.
isBlank
(
entity
.
getUpdaterId
()))
{
entity
.
setUpdaterId
(
"system"
);
}
}
}
catch
(
Exception
e
)
{
// 不允许修改 ruleBizId 和 isDeleted
return
original
;
entity
.
setRuleBizId
(
null
);
entity
.
setIsDeleted
(
null
);
entity
.
setCreateTime
(
null
);
}
}
return
super
.
saveOrUpdate
(
entity
);
}
}
}
}
\ No newline at end of file
yd-communication-service/src/main/java/com/yd/communication/service/service/impl/CoOperationLogServiceImpl.java
View file @
655980ca
...
@@ -5,6 +5,7 @@ import com.yd.communication.service.dao.CoOperationLogMapper;
...
@@ -5,6 +5,7 @@ import com.yd.communication.service.dao.CoOperationLogMapper;
import
com.yd.communication.service.service.ICoOperationLogService
;
import
com.yd.communication.service.service.ICoOperationLogService
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.scheduling.annotation.Async
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
/**
/**
...
@@ -21,6 +22,7 @@ import org.springframework.stereotype.Service;
...
@@ -21,6 +22,7 @@ import org.springframework.stereotype.Service;
public
class
CoOperationLogServiceImpl
extends
ServiceImpl
<
CoOperationLogMapper
,
CoOperationLog
>
implements
ICoOperationLogService
{
public
class
CoOperationLogServiceImpl
extends
ServiceImpl
<
CoOperationLogMapper
,
CoOperationLog
>
implements
ICoOperationLogService
{
@Override
@Override
@Async
(
"communicationExecutor"
)
public
void
log
(
String
bizId
,
String
operatorId
,
String
operatorType
,
public
void
log
(
String
bizId
,
String
operatorId
,
String
operatorType
,
String
operatorName
,
String
action
,
String
content
,
String
operatorName
,
String
action
,
String
content
,
String
deviceNumber
,
String
ip
)
{
String
deviceNumber
,
String
ip
)
{
...
...
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