Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
GeoFlyApi
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
GeoFly
GeoFlyApi
Commits
bdb026b6
Commit
bdb026b6
authored
Mar 19, 2026
by
tntxia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
安全整改的问题修改
parent
41a1df5a
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
218 additions
and
47 deletions
+218
-47
pom.xml
+16
-0
sample/src/main/java/com/dji/sample/ai/service/impl/AiInfoServiceImpl.java
+65
-3
sample/src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java
+8
-3
sample/src/main/java/com/dji/sample/component/websocket/config/MyWebSocketHandler.java
+98
-11
sample/src/main/java/com/dji/sample/manage/controller/UserController.java
+2
-1
sample/src/main/resources/application.yml
+29
-29
No files found.
pom.xml
View file @
bdb026b6
...
...
@@ -85,6 +85,22 @@
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<version>
3.10.1
</version>
<!-- JDK 11 推荐用 3.8+ 版本 -->
<configuration>
<!-- 统一为 JDK 11,消除版本不匹配警告 -->
<release>
11
</release>
<encoding>
UTF-8
</encoding>
<!-- 可选:关闭严格泛型检查(避免额外报错) -->
<compilerArgs>
<arg>
-Xlint:-unchecked
</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
sample/src/main/java/com/dji/sample/ai/service/impl/AiInfoServiceImpl.java
View file @
bdb026b6
...
...
@@ -56,9 +56,71 @@ public class AiInfoServiceImpl extends ServiceImpl<IAiInfoMapper, AiInfoEntity>
String
[]
arr
=
param
.
getOrderBy
().
split
(
" "
);
String
column
=
arr
[
0
];
String
desc
=
arr
.
length
>
1
?
arr
[
1
]
:
"desc"
;
wrapper
.
last
(
Objects
.
nonNull
(
param
.
getOrderBy
()),
" order by "
+
column
+
" "
+
desc
);
String
direction
=
arr
.
length
>
1
?
arr
[
1
]
:
"desc"
;
// 避免SQL注入,不直接使用SQL语句,所以判断相应的列
switch
(
column
)
{
case
"id"
:
if
(
"asc"
.
equals
(
direction
))
{
wrapper
.
orderByAsc
(
AiInfoEntity:
:
getId
);
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getId
);
}
break
;
case
"createTime"
:
case
"create_time"
:
if
(
"asc"
.
equals
(
direction
))
{
wrapper
.
orderByAsc
(
AiInfoEntity:
:
getCreateTime
);
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getCreateTime
);
}
break
;
case
"warnTime"
:
case
"warn_time"
:
if
(
"asc"
.
equals
(
direction
))
{
wrapper
.
orderByAsc
(
AiInfoEntity:
:
getWarnTime
);
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getWarnTime
);
}
break
;
case
"deviceSn"
:
case
"device_sn"
:
if
(
"asc"
.
equals
(
direction
))
{
wrapper
.
orderByAsc
(
AiInfoEntity:
:
getDeviceSn
);
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getDeviceSn
);
}
break
;
case
"warnType"
:
case
"warn_type"
:
if
(
"asc"
.
equals
(
direction
))
{
wrapper
.
orderByAsc
(
AiInfoEntity:
:
getWarnType
);
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getWarnType
);
}
break
;
case
"warnEvent"
:
case
"warn_event"
:
if
(
"asc"
.
equals
(
direction
))
{
wrapper
.
orderByAsc
(
AiInfoEntity:
:
getWarnEvent
);
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getWarnEvent
);
}
break
;
case
"algorithmType"
:
case
"algorithm_type"
:
if
(
"asc"
.
equals
(
direction
))
{
wrapper
.
orderByAsc
(
AiInfoEntity:
:
getAlgorithmType
);
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getAlgorithmType
);
}
break
;
default
:
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getId
);
break
;
}
}
else
{
wrapper
.
orderByDesc
(
AiInfoEntity:
:
getId
);
}
Page
<
AiInfoEntity
>
pagination
=
this
.
page
(
new
Page
<>(
page
,
pageSize
),
wrapper
);
...
...
sample/src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java
View file @
bdb026b6
...
...
@@ -32,19 +32,20 @@ public class AuthPrincipalHandler extends DefaultHandshakeHandler {
HttpServletRequest
servletRequest
=
((
ServletServerHttpRequest
)
request
).
getServletRequest
();
String
token
=
servletRequest
.
getParameter
(
AuthInterceptor
.
PARAM_TOKEN
);
// 默认让WebSocket的认证都通过
if
(!
StringUtils
.
hasText
(
token
))
{
return
fals
e
;
return
tru
e
;
}
log
.
debug
(
"token:"
+
token
);
Optional
<
CustomClaim
>
customClaim
=
JwtUtil
.
parseToken
(
token
);
if
(
customClaim
.
isEmpty
())
{
return
fals
e
;
return
tru
e
;
}
servletRequest
.
setAttribute
(
AuthInterceptor
.
TOKEN_CLAIM
,
customClaim
.
get
());
return
true
;
}
return
fals
e
;
return
tru
e
;
}
...
...
@@ -63,6 +64,10 @@ public class AuthPrincipalHandler extends DefaultHandshakeHandler {
CustomClaim
claim
=
(
CustomClaim
)
((
ServletServerHttpRequest
)
request
).
getServletRequest
()
.
getAttribute
(
AuthInterceptor
.
TOKEN_CLAIM
);
if
(
claim
==
null
)
{
return
()
->
null
;
}
return
()
->
claim
.
getWorkspaceId
()
+
"/"
+
claim
.
getUserType
()
+
"/"
+
claim
.
getId
();
}
return
()
->
null
;
...
...
sample/src/main/java/com/dji/sample/component/websocket/config/MyWebSocketHandler.java
View file @
bdb026b6
package
com
.
dji
.
sample
.
component
.
websocket
.
config
;
import
com.dji.sample.common.model.CustomClaim
;
import
com.dji.sample.common.util.JwtUtil
;
import
com.dji.sample.component.websocket.service.IWebSocketManageService
;
import
com.dji.sdk.websocket.WebSocketDefaultHandler
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.socket.CloseStatus
;
...
...
@@ -10,6 +14,9 @@ import org.springframework.web.socket.WebSocketMessage;
import
org.springframework.web.socket.WebSocketSession
;
import
java.security.Principal
;
import
java.util.Map
;
import
java.util.Optional
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
*
...
...
@@ -22,6 +29,10 @@ public class MyWebSocketHandler extends WebSocketDefaultHandler {
private
IWebSocketManageService
webSocketManageService
;
private
ObjectMapper
objectMapper
=
new
ObjectMapper
();
private
Map
<
String
,
Boolean
>
authenticatedSessions
=
new
ConcurrentHashMap
<>();
private
Map
<
String
,
CustomClaim
>
sessionClaims
=
new
ConcurrentHashMap
<>();
MyWebSocketHandler
(
WebSocketHandler
delegate
,
IWebSocketManageService
webSocketManageService
)
{
super
(
delegate
);
this
.
webSocketManageService
=
webSocketManageService
;
...
...
@@ -30,29 +41,104 @@ public class MyWebSocketHandler extends WebSocketDefaultHandler {
@Override
public
void
afterConnectionEstablished
(
WebSocketSession
session
)
throws
Exception
{
Principal
principal
=
session
.
getPrincipal
();
if
(
StringUtils
.
hasText
(
principal
.
getName
()))
{
webSocketManageService
.
put
(
principal
.
getName
(),
new
MyConcurrentWebSocketSession
(
session
));
log
.
debug
(
"{} is connected. ID: {}. WebSocketSession[current count: {}]"
,
principal
.
getName
(),
session
.
getId
(),
webSocketManageService
.
getConnectedCount
());
return
;
String
principalName
=
principal
.
getName
();
if
(
StringUtils
.
hasText
(
principalName
)
&&
!
principalName
.
startsWith
(
"temp-"
))
{
webSocketManageService
.
put
(
principalName
,
new
MyConcurrentWebSocketSession
(
session
));
authenticatedSessions
.
put
(
session
.
getId
(),
true
);
log
.
debug
(
"{} is connected (pre-authenticated). ID: {}. WebSocketSession[current count: {}]"
,
principalName
,
session
.
getId
(),
webSocketManageService
.
getConnectedCount
());
}
else
{
log
.
debug
(
"Unauthenticated connection established. ID: {}, temp principal: {}"
,
session
.
getId
(),
principalName
);
}
session
.
close
();
}
@Override
public
void
afterConnectionClosed
(
WebSocketSession
session
,
CloseStatus
closeStatus
)
throws
Exception
{
Principal
principal
=
session
.
getPrincipal
();
if
(
StringUtils
.
hasText
(
principal
.
getName
()))
{
webSocketManageService
.
remove
(
principal
.
getName
(),
session
.
getId
());
String
sessionId
=
session
.
getId
();
Boolean
isAuthenticated
=
authenticatedSessions
.
get
(
sessionId
);
if
(
Boolean
.
TRUE
.
equals
(
isAuthenticated
))
{
CustomClaim
claim
=
sessionClaims
.
get
(
sessionId
);
if
(
claim
!=
null
)
{
String
key
=
claim
.
getWorkspaceId
()
+
"/"
+
claim
.
getUserType
()
+
"/"
+
claim
.
getId
();
webSocketManageService
.
remove
(
key
,
sessionId
);
log
.
debug
(
"{} is disconnected. ID: {}. WebSocketSession[current count: {}]"
,
principal
.
getName
(),
session
.
getId
(),
webSocketManageService
.
getConnectedCount
());
key
,
sessionId
,
webSocketManageService
.
getConnectedCount
());
}
}
authenticatedSessions
.
remove
(
sessionId
);
sessionClaims
.
remove
(
sessionId
);
}
@Override
public
void
handleMessage
(
WebSocketSession
session
,
WebSocketMessage
<?>
message
)
throws
Exception
{
log
.
debug
(
"received message: {}"
,
message
.
getPayload
());
String
sessionId
=
session
.
getId
();
Boolean
isAuthenticated
=
authenticatedSessions
.
get
(
sessionId
);
String
payload
=
message
.
getPayload
().
toString
();
log
.
debug
(
"Received message from session {}: {}"
,
sessionId
,
payload
);
try
{
JsonNode
jsonNode
=
objectMapper
.
readTree
(
payload
);
String
type
=
jsonNode
.
has
(
"type"
)
?
jsonNode
.
get
(
"type"
).
asText
()
:
null
;
if
(
"auth"
.
equals
(
type
)
&&
!
Boolean
.
TRUE
.
equals
(
isAuthenticated
))
{
String
token
=
jsonNode
.
has
(
"token"
)
?
jsonNode
.
get
(
"token"
).
asText
()
:
null
;
if
(
StringUtils
.
hasText
(
token
))
{
Optional
<
CustomClaim
>
customClaimOpt
=
JwtUtil
.
parseToken
(
token
);
if
(
customClaimOpt
.
isPresent
())
{
CustomClaim
claim
=
customClaimOpt
.
get
();
String
key
=
claim
.
getWorkspaceId
()
+
"/"
+
claim
.
getUserType
()
+
"/"
+
claim
.
getId
();
authenticatedSessions
.
put
(
sessionId
,
true
);
sessionClaims
.
put
(
sessionId
,
claim
);
webSocketManageService
.
put
(
key
,
new
MyConcurrentWebSocketSession
(
session
));
log
.
debug
(
"Session {} authenticated successfully. User: {}"
,
sessionId
,
key
);
String
authResponse
=
objectMapper
.
writeValueAsString
(
Map
.
of
(
"type"
,
"auth_success"
,
"status"
,
"ok"
));
session
.
sendMessage
(
new
org
.
springframework
.
web
.
socket
.
TextMessage
(
authResponse
));
return
;
}
}
log
.
warn
(
"Authentication failed for session {}"
,
sessionId
);
String
authFail
=
objectMapper
.
writeValueAsString
(
Map
.
of
(
"type"
,
"auth_fail"
,
"status"
,
"error"
,
"message"
,
"Invalid token"
));
session
.
sendMessage
(
new
org
.
springframework
.
web
.
socket
.
TextMessage
(
authFail
));
session
.
close
(
CloseStatus
.
NOT_ACCEPTABLE
);
return
;
}
if
(!
Boolean
.
TRUE
.
equals
(
isAuthenticated
))
{
log
.
warn
(
"Unauthenticated session {} tried to send message. Closing."
,
sessionId
);
String
authRequired
=
objectMapper
.
writeValueAsString
(
Map
.
of
(
"type"
,
"auth_required"
,
"message"
,
"Please authenticate first"
));
session
.
sendMessage
(
new
org
.
springframework
.
web
.
socket
.
TextMessage
(
authRequired
));
// session.close(CloseStatus.NOT_ACCEPTABLE);
return
;
}
super
.
handleMessage
(
session
,
message
);
}
catch
(
Exception
e
)
{
log
.
error
(
"Error handling message from session {}"
,
sessionId
,
e
);
if
(!
Boolean
.
TRUE
.
equals
(
isAuthenticated
))
{
session
.
close
(
CloseStatus
.
BAD_DATA
);
}
}
}
}
\ No newline at end of file
sample/src/main/java/com/dji/sample/manage/controller/UserController.java
View file @
bdb026b6
...
...
@@ -152,7 +152,7 @@ public class UserController {
}
/**
*
Admin resets a user's
password.
*
User reset
password.
* The new password must comply with all password rules.
*
* @param request HTTP request
...
...
@@ -162,6 +162,7 @@ public class UserController {
@PostMapping
(
"/resetPassword"
)
public
HttpResultResponse
<
Object
>
resetPassword
(
HttpServletRequest
request
,
@RequestBody
ChangePasswordParam
param
)
{
CustomClaim
customClaim
=
(
CustomClaim
)
request
.
getAttribute
(
TOKEN_CLAIM
);
String
userId
=
customClaim
.
getId
();
return
userService
.
resetPassword
(
userId
,
param
);
...
...
sample/src/main/resources/application.yml
View file @
bdb026b6
...
...
@@ -14,10 +14,10 @@ spring:
druid
:
type
:
com.alibaba.druid.pool.DruidDataSource
driver-class-name
:
com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://geoair_mysql:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true
url
:
jdbc:mysql://geoair_mysql:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
# url: jdbc:mysql://cloud_api_sample_mysql:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true
# 深圳
url
:
jdbc:mysql://cloud_api_sample_mysql:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
# url: jdbc:mysql://cloud_api_sample_mysql:3306/cloud_sample?useSSL=false&allowPublicKeyRetrieval=true
username
:
root
password
:
root
initial-size
:
10
...
...
@@ -26,10 +26,10 @@ spring:
max-wait
:
60000
redis
:
#
host: geoair_redis
host
:
geoair_redis
# host: cloud_api_sample_redis
# 深圳
host
:
cloud_api_sample_redis
#
host: cloud_api_sample_redis
port
:
6379
database
:
0
username
:
# if you enable
...
...
@@ -60,21 +60,23 @@ jwt:
age
:
86400
mqtt
:
# @see com.dji.sample.component.mqtt.model.MqttUseEnum
# BASIC parameters are required.
NET
:
# protocol: MQTT # @see com.dji.sample.component.mqtt.model.MqttProtocolEnum
# host: 183.11.236.162
# port: 54418
# username: JavaServer
# password: 123456
# client-id: 123456
# protocol: MQTT # @see com.dji.sample.component.mqtt.model.MqttProtocolEnum
# host: 183.11.236.162
# port: 54418
# username: JavaServer
# password: 123456
# client-id: 123456
protocol
:
WSS
host
:
geofly.geotwin.c
n
host
:
geofly.geotwin.c
c
port
:
443
path
:
/mqtt
username
:
JavaServer
password
:
123456
# @see com.dji.sample.component.mqtt.model.MqttUseEnum
# BASIC parameters are required.
BASIC
:
protocol
:
MQTT
# @see com.dji.sample.component.mqtt.model.MqttProtocolEnum
# 深圳
...
...
@@ -84,10 +86,10 @@ mqtt:
# host: emqx-broker
# host: 192.168.32.90
# port: 44418
#
host: 203.186.109.106
#
port: 54941
host
:
emqx-broker
port
:
1883
host
:
203.186.109.106
port
:
54941
#
host: emqx-broker
#
port: 1883
username
:
JavaServer
password
:
123456
client-id
:
123456
...
...
@@ -95,16 +97,16 @@ mqtt:
path
:
DRC
:
# 深圳
protocol
:
WS
S
host
:
geofly.geotwin.cn
port
:
443
#
protocol: WSS # @see com.dji.sample.component.mqtt.model.MqttProtocolEnum
# protocol: W
S
# host: 183.11.236.162
# port: 54419
protocol
:
WSS
# @see com.dji.sample.component.mqtt.model.MqttProtocolEnum
# host: emqx-broker
# host: 192.168.32.90
# port: 8083
# host: geofly-dev.geotwin.cc
#
host: geofly.geotwin.cc
#
port: 443
host
:
geofly.geotwin.cc
port
:
443
path
:
/mqtt
username
:
JavaServer
password
:
123456
...
...
@@ -112,7 +114,7 @@ mqtt:
cloud-sdk
:
mqtt
:
# Topics that need to be subscribed when initially connecting to mqtt, multiple topics are divided by ",".
inbound-topic
:
sys/product/+/status,thing/product/+/requests,
thing/product/+/osd,
/ai_info
inbound-topic
:
sys/product/+/status,thing/product/+/requests,/ai_info
url
:
manage
:
...
...
@@ -167,10 +169,9 @@ url:
oss
:
enable
:
true
provider
:
minio
# 香港
# endpoint: https://gt7-oss.geotwin.cc
endpoint
:
https://gt7-oss.geotwin.cc
# 深圳
endpoint
:
https://gt-oss-dev.geotwin.cn
#
endpoint: https://gt-oss-dev.geotwin.cn
access-key
:
minioadmin
secret-key
:
minioadmin
bucket
:
gtfly
...
...
@@ -211,10 +212,9 @@ livestream:
# RTMP Note: This IP is the address of the streaming server. If you want to see livestream on web page, you need to convert the RTMP stream to WebRTC stream.
rtmp
:
#
url: rtmp://203.186.109.106:44424/live/ # Example: 'rtmp://192.168.1.1/live/'
url
:
rtmp://203.186.109.106:44424/live/
# Example: 'rtmp://192.168.1.1/live/'
# 深圳
# url: rtmp://183.11.236.162:54424/live/ # Example: 'rtmp://192.168.1.1/live/'
url
:
rtmp://183.11.236.162:54460/live/
# Example: 'rtmp://192.168.1.1/live/'
rtsp
:
username
:
Please enter the username.
password
:
Please enter the password.
...
...
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