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
7920a055
Commit
7920a055
authored
Mar 12, 2026
by
tntxia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
登录错误次数限制和登录日志
parent
8eab34eb
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
500 additions
and
4 deletions
+500
-4
sample/src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java
+39
-0
sample/src/main/java/com/dji/sample/manage/dao/ILoginLogMapper.java
+8
-0
sample/src/main/java/com/dji/sample/manage/model/dto/LoginLogDTO.java
+28
-0
sample/src/main/java/com/dji/sample/manage/model/entity/LoginLogEntity.java
+36
-0
sample/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java
+10
-0
sample/src/main/java/com/dji/sample/manage/model/param/searchParam/LoginLogSearchParam.java
+23
-0
sample/src/main/java/com/dji/sample/manage/model/param/searchParam/OperateLogSearchParam.java
+29
-0
sample/src/main/java/com/dji/sample/manage/service/ILoginLogService.java
+22
-0
sample/src/main/java/com/dji/sample/manage/service/IUserService.java
+13
-0
sample/src/main/java/com/dji/sample/manage/service/impl/LoginLogService.java
+139
-0
sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
+153
-4
No files found.
sample/src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java
View file @
7920a055
...
...
@@ -110,6 +110,45 @@ public class RedisOpsUtils {
return
redisTemplate
.
opsForValue
().
get
(
key
);
}
/**
* GET Integer
*
* @param key key
* @return result
*/
public
static
Integer
getInt
(
String
key
)
{
Object
obj
=
get
(
key
);
if
(
obj
==
null
)
{
return
0
;
}
if
(
obj
instanceof
Integer
)
{
return
(
Integer
)
obj
;
}
if
(
obj
instanceof
Long
)
{
return
((
Long
)
obj
).
intValue
();
}
if
(
obj
instanceof
Double
)
{
return
((
Double
)
obj
).
intValue
();
}
if
(
obj
instanceof
Float
)
{
return
((
Float
)
obj
).
intValue
();
}
if
(
obj
instanceof
Boolean
)
{
Boolean
bool
=
(
Boolean
)
obj
;
return
bool
?
1
:
0
;
}
return
Integer
.
parseInt
(
obj
.
toString
());
}
/**
* SETEX
* @param key
...
...
sample/src/main/java/com/dji/sample/manage/dao/ILoginLogMapper.java
0 → 100644
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
dao
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.dji.sample.manage.model.entity.LoginLogEntity
;
public
interface
ILoginLogMapper
extends
BaseMapper
<
LoginLogEntity
>
{
}
sample/src/main/java/com/dji/sample/manage/model/dto/LoginLogDTO.java
0 → 100644
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
model
.
dto
;
import
lombok.Builder
;
import
lombok.Data
;
import
java.io.Serializable
;
@Builder
@Data
public
class
LoginLogDTO
implements
Serializable
{
private
Integer
id
;
private
String
userId
;
private
String
username
;
private
String
message
;
private
boolean
success
;
private
String
ipAddress
;
private
String
userAgent
;
private
Long
createTime
;
}
sample/src/main/java/com/dji/sample/manage/model/entity/LoginLogEntity.java
0 → 100644
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
model
.
entity
;
import
com.baomidou.mybatisplus.annotation.*
;
import
lombok.Data
;
import
java.io.Serializable
;
@TableName
(
value
=
"login_log"
)
@Data
public
class
LoginLogEntity
implements
Serializable
{
@TableId
(
type
=
IdType
.
AUTO
)
private
Integer
id
;
@TableField
(
value
=
"user_id"
)
private
String
userId
;
@TableField
(
value
=
"username"
)
private
String
username
;
@TableField
(
value
=
"message"
)
private
String
message
;
@TableField
(
value
=
"success"
)
private
boolean
success
;
@TableField
(
value
=
"ip_address"
)
private
String
ipAddress
;
@TableField
(
value
=
"user_agent"
)
private
String
userAgent
;
@TableField
(
value
=
"create_time"
,
fill
=
FieldFill
.
INSERT
)
private
Long
createTime
;
}
sample/src/main/java/com/dji/sample/manage/model/entity/UserEntity.java
View file @
7920a055
...
...
@@ -42,4 +42,14 @@ public class UserEntity implements Serializable {
@TableField
(
value
=
"role_type"
)
private
Integer
roleType
;
@TableField
(
value
=
"login_try_count"
)
private
Integer
loginTryCount
;
@TableField
(
value
=
"new_add"
)
private
Boolean
newAdd
;
@TableField
(
value
=
"last_change_password"
)
private
Long
lastChangePassword
;
}
sample/src/main/java/com/dji/sample/manage/model/param/searchParam/LoginLogSearchParam.java
0 → 100644
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
model
.
param
.
searchParam
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
lombok.Data
;
/**
* @author chenshixian
**/
@Data
public
class
LoginLogSearchParam
{
@JsonProperty
(
"userId"
)
private
String
userId
;
@JsonProperty
(
"startDate"
)
private
String
startDate
;
@JsonProperty
(
"endDate"
)
private
String
endDate
;
}
sample/src/main/java/com/dji/sample/manage/model/param/searchParam/OperateLogSearchParam.java
0 → 100644
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
model
.
param
.
searchParam
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
lombok.Data
;
/**
* @author chenshixian
**/
@Data
public
class
OperateLogSearchParam
{
@JsonProperty
(
"userId"
)
private
String
userId
;
@JsonProperty
(
"operateType"
)
private
String
operateType
;
@JsonProperty
(
"startDate"
)
private
String
startDate
;
@JsonProperty
(
"endDate"
)
private
String
endDate
;
@JsonProperty
(
"deviceSn"
)
private
String
deviceSn
;
}
sample/src/main/java/com/dji/sample/manage/service/ILoginLogService.java
0 → 100644
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
service
;
import
com.dji.sample.manage.model.dto.LoginLogDTO
;
import
com.dji.sample.manage.model.entity.UserEntity
;
import
com.dji.sample.manage.model.param.searchParam.LoginLogSearchParam
;
import
com.dji.sdk.common.PaginationData
;
/**
* @author chenshixian
**/
public
interface
ILoginLogService
{
void
addLoginLog
(
UserEntity
userEntity
,
boolean
success
,
String
message
);
void
addLoginLog
(
UserEntity
userEntity
,
boolean
success
,
String
message
,
String
ipAddress
,
String
userAgent
);
void
addLoginLog
(
String
username
,
boolean
success
,
String
message
,
String
ipAddress
,
String
userAgent
);
PaginationData
<
LoginLogDTO
>
getLoginLogList
(
LoginLogSearchParam
param
,
int
page
,
int
size
);
}
sample/src/main/java/com/dji/sample/manage/service/IUserService.java
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
service
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.dji.sample.manage.model.dto.LoginLogDTO
;
import
com.dji.sample.manage.model.dto.UserDTO
;
import
com.dji.sample.manage.model.dto.UserListDTO
;
import
com.dji.sample.manage.model.dto.UserLoginDTO
;
import
com.dji.sample.manage.model.entity.UserEntity
;
import
com.dji.sample.manage.model.param.searchParam.LoginLogSearchParam
;
import
com.dji.sample.manage.model.param.searchParam.UserSearchParam
;
import
com.dji.sdk.common.HttpResultResponse
;
import
com.dji.sdk.common.PaginationData
;
...
...
@@ -22,6 +24,17 @@ public interface IUserService extends IService<UserEntity> {
HttpResultResponse
getUserByUsername
(
String
username
,
String
workspaceId
);
/**
* get user login log
*
* @param userId 用户ID
* @param roleType 角色类型
*
* @return 结果
*/
PaginationData
<
LoginLogDTO
>
getUserLoginLog
(
LoginLogSearchParam
param
,
String
userId
,
Integer
roleType
,
int
page
,
int
pageSize
);
/**
* Verify the username and password to log in.
* @param username
* @param password
...
...
sample/src/main/java/com/dji/sample/manage/service/impl/LoginLogService.java
0 → 100644
View file @
7920a055
package
com
.
dji
.
sample
.
manage
.
service
.
impl
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.dji.sample.common.util.DateUtil
;
import
com.dji.sample.manage.dao.ILoginLogMapper
;
import
com.dji.sample.manage.model.dto.LoginLogDTO
;
import
com.dji.sample.manage.model.entity.LoginLogEntity
;
import
com.dji.sample.manage.model.entity.UserEntity
;
import
com.dji.sample.manage.model.param.searchParam.LoginLogSearchParam
;
import
com.dji.sample.manage.service.ILoginLogService
;
import
com.dji.sdk.common.PaginationData
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
* @author chenshixian
**/
@Service
public
class
LoginLogService
implements
ILoginLogService
{
@Autowired
private
ILoginLogMapper
loginLogMapper
;
/**
* 保存登录信息
* @param userEntity
* @param success
* @param message
*/
@Override
public
void
addLoginLog
(
UserEntity
userEntity
,
boolean
success
,
String
message
)
{
addLoginLog
(
userEntity
,
success
,
message
,
null
,
null
);
}
/**
* 保存登录信息(包含IP和User Agent)
*
* @param userEntity
* @param success
* @param message
* @param ipAddress
* @param userAgent
*/
@Override
public
void
addLoginLog
(
UserEntity
userEntity
,
boolean
success
,
String
message
,
String
ipAddress
,
String
userAgent
)
{
LoginLogEntity
loginLogEntity
=
new
LoginLogEntity
();
loginLogEntity
.
setUserId
(
userEntity
.
getUserId
());
loginLogEntity
.
setUsername
(
userEntity
.
getUsername
());
loginLogEntity
.
setSuccess
(
success
);
loginLogEntity
.
setMessage
(
message
);
loginLogEntity
.
setIpAddress
(
ipAddress
);
loginLogEntity
.
setUserAgent
(
userAgent
);
loginLogEntity
.
setCreateTime
(
System
.
currentTimeMillis
());
loginLogMapper
.
insert
(
loginLogEntity
);
}
/**
* 保存登录信息(仅用户名,用于登录失败场景)
*
* @param username
* @param success
* @param message
* @param ipAddress
* @param userAgent
*/
@Override
public
void
addLoginLog
(
String
username
,
boolean
success
,
String
message
,
String
ipAddress
,
String
userAgent
)
{
LoginLogEntity
loginLogEntity
=
new
LoginLogEntity
();
loginLogEntity
.
setUserId
(
""
);
loginLogEntity
.
setUsername
(
username
);
loginLogEntity
.
setSuccess
(
success
);
loginLogEntity
.
setMessage
(
message
);
loginLogEntity
.
setIpAddress
(
ipAddress
);
loginLogEntity
.
setUserAgent
(
userAgent
);
loginLogEntity
.
setCreateTime
(
System
.
currentTimeMillis
());
loginLogMapper
.
insert
(
loginLogEntity
);
}
private
LoginLogDTO
entity2DTO
(
LoginLogEntity
entity
)
{
LoginLogDTO
.
LoginLogDTOBuilder
builder
=
LoginLogDTO
.
builder
();
if
(
entity
!=
null
)
{
builder
.
userId
(
entity
.
getUserId
())
.
id
(
entity
.
getId
())
.
userId
(
entity
.
getUserId
())
.
username
(
entity
.
getUsername
())
.
success
(
entity
.
isSuccess
())
.
message
(
entity
.
getMessage
())
.
ipAddress
(
entity
.
getIpAddress
())
.
userAgent
(
entity
.
getUserAgent
())
.
createTime
(
entity
.
getCreateTime
());
}
return
builder
.
build
();
}
@Override
public
PaginationData
<
LoginLogDTO
>
getLoginLogList
(
LoginLogSearchParam
param
,
int
page
,
int
pageSize
)
{
LambdaQueryWrapper
<
LoginLogEntity
>
queryWrapper
=
new
LambdaQueryWrapper
<>();
if
(
param
!=
null
)
{
if
(
StringUtils
.
isNotBlank
(
param
.
getUserId
()))
{
queryWrapper
.
eq
(
LoginLogEntity:
:
getUserId
,
param
.
getUserId
());
}
if
(
StringUtils
.
isNotBlank
(
param
.
getStartDate
()))
{
String
startDate
=
param
.
getStartDate
();
startDate
+=
" 00:00:00"
;
queryWrapper
.
ge
(
LoginLogEntity:
:
getCreateTime
,
DateUtil
.
getTimeStampFromDateStr
(
startDate
));
}
if
(
StringUtils
.
isNotBlank
(
param
.
getEndDate
()))
{
String
startDate
=
param
.
getStartDate
();
startDate
+=
" 23:59:59"
;
queryWrapper
.
lt
(
LoginLogEntity:
:
getCreateTime
,
DateUtil
.
getTimeStampFromDateStrNext
(
startDate
));
}
}
queryWrapper
.
orderByDesc
(
LoginLogEntity:
:
getCreateTime
);
Page
<
LoginLogEntity
>
userEntityPage
=
loginLogMapper
.
selectPage
(
new
Page
<>(
page
,
pageSize
),
queryWrapper
);
List
<
LoginLogDTO
>
usersList
=
userEntityPage
.
getRecords
()
.
stream
()
.
map
(
this
::
entity2DTO
)
.
collect
(
Collectors
.
toList
());
return
PaginationData
.
of
(
usersList
,
userEntityPage
.
getTotal
(),
page
,
pageSize
);
}
}
sample/src/main/java/com/dji/sample/manage/service/impl/UserServiceImpl.java
View file @
7920a055
...
...
@@ -14,6 +14,8 @@ import com.dji.sample.common.util.SecurityUtils;
import
com.dji.sample.component.mqtt.config.MqttPropertyConfiguration
;
import
com.dji.sample.component.oss.model.OssConfiguration
;
import
com.dji.sample.component.oss.service.impl.OssServiceContext
;
import
com.dji.sample.component.redis.RedisConst
;
import
com.dji.sample.component.redis.RedisOpsUtils
;
import
com.dji.sample.manage.dao.IUserMapper
;
import
com.dji.sample.manage.model.dto.*
;
import
com.dji.sample.manage.model.entity.OrgEntity
;
...
...
@@ -22,11 +24,9 @@ import com.dji.sample.manage.model.entity.UserOrgEntity;
import
com.dji.sample.manage.model.entity.WorkspaceEntity
;
import
com.dji.sample.manage.model.enums.RoleTypeEnum
;
import
com.dji.sample.manage.model.enums.UserTypeEnum
;
import
com.dji.sample.manage.model.param.searchParam.LoginLogSearchParam
;
import
com.dji.sample.manage.model.param.searchParam.UserSearchParam
;
import
com.dji.sample.manage.service.IOrgService
;
import
com.dji.sample.manage.service.IUserOrgService
;
import
com.dji.sample.manage.service.IUserService
;
import
com.dji.sample.manage.service.IWorkspaceService
;
import
com.dji.sample.manage.service.*
;
import
com.dji.sdk.common.HttpResultResponse
;
import
com.dji.sdk.common.Pagination
;
import
com.dji.sdk.common.PaginationData
;
...
...
@@ -61,6 +61,10 @@ public class UserServiceImpl extends ServiceImpl<IUserMapper, UserEntity> implem
@Autowired
private
IOrgService
orgService
;
@Autowired
private
ILoginLogService
loginLogService
;
@Autowired
private
IUserOrgService
userOrgService
;
...
...
@@ -70,6 +74,45 @@ public class UserServiceImpl extends ServiceImpl<IUserMapper, UserEntity> implem
@Autowired
private
OssServiceContext
ossService
;
/**
* 登录尝试次数
*/
public
static
final
String
LOGIN_TRY_COUNT
=
"LOGIN_TRY_COUNT"
;
private
final
static
String
LOGIN_USER_NOT_PASS
=
"username or password invalid"
;
private
final
static
String
LOGIN_USER_NAME_NOT_EXIST
=
"user name does not exist"
;
private
final
static
String
ACCOUNT_TYPE_NOT_MATCH
=
"Account type does not match"
;
private
final
static
String
INVALID_PASSWORD
=
"Invalid password"
;
private
final
static
String
INVALID_WORKSPACE
=
"Invalid workspace"
;
/**
* 最大尝试登录次数
*/
private
final
static
Integer
LOGIN_TRY_COUNT_MAX
=
5
;
/**
* 最大尝试登录次数
* 第二阶段
*/
private
final
static
Integer
LOGIN_TRY_COUNT_MAX_SECOND
=
10
;
/**
* 登录尝试的锁
*/
private
final
static
String
LOGIN_TRY_LOCK
=
"LOGIN_TRY_LOCK"
;
private
final
static
String
LOGIN_TRY_COUNT_MAX_EXCEEDED
=
"login try count max exceeded, user locked"
;
private
final
static
long
HOUR_SECONDS
=
60
*
60
;
private
final
static
long
DATE_SECONDS
=
24
*
60
*
60
;
@Override
public
HttpResultResponse
getUserByUsername
(
String
username
,
String
workspaceId
)
{
...
...
@@ -86,6 +129,109 @@ public class UserServiceImpl extends ServiceImpl<IUserMapper, UserEntity> implem
return
HttpResultResponse
.
success
(
user
);
}
@Override
public
PaginationData
<
LoginLogDTO
>
getUserLoginLog
(
LoginLogSearchParam
param
,
String
userId
,
Integer
roleType
,
int
page
,
int
pageSize
)
{
if
(
param
==
null
)
{
param
=
new
LoginLogSearchParam
();
}
if
(
roleType
==
null
||
roleType
!=
RoleTypeEnum
.
ADMIN
.
getVal
())
{
param
.
setUserId
(
userId
);
}
return
loginLogService
.
getLoginLogList
(
param
,
page
,
pageSize
);
}
/**
* 更新用户尝试登录次数
*
* @param user 用户
* @param loginTryCount 登录尝试次数
*/
private
void
updateUserLoginTryCount
(
UserEntity
user
,
Integer
loginTryCount
)
{
LambdaUpdateWrapper
<
UserEntity
>
updateWrapper
=
new
LambdaUpdateWrapper
<>();
updateWrapper
.
set
(
UserEntity:
:
getLoginTryCount
,
loginTryCount
);
updateWrapper
.
eq
(
UserEntity:
:
getId
,
user
.
getId
());
mapper
.
update
(
null
,
updateWrapper
);
}
/**
* 解锁用户
*
* @param userEntity 实体
*/
public
void
unlockUser
(
UserEntity
userEntity
)
{
String
username
=
userEntity
.
getUsername
();
updateUserLoginTryCount
(
userEntity
,
0
);
RedisOpsUtils
.
del
(
LOGIN_TRY_COUNT
+
RedisConst
.
DELIMITER
+
username
);
RedisOpsUtils
.
del
(
LOGIN_TRY_LOCK
+
RedisConst
.
DELIMITER
+
username
);
}
/**
* 处理登录密码错误的问题
*/
private
void
handleLoginPasswordFail
(
String
ipAddress
,
String
userAgent
,
UserEntity
userEntity
)
{
Integer
loginTryCount
=
userEntity
.
getLoginTryCount
();
if
(
loginTryCount
==
null
)
{
loginTryCount
=
0
;
}
loginTryCount
++;
// 更新用户尝试登录次数
updateUserLoginTryCount
(
userEntity
,
loginTryCount
);
// 把登录尝试次数放在Redis中
addLoginTryCountToRedis
(
userEntity
.
getUsername
());
// 增加登录日志
loginLogService
.
addLoginLog
(
userEntity
,
false
,
INVALID_PASSWORD
,
ipAddress
,
userAgent
);
}
private
void
addLoginTryCountToRedis
(
String
username
)
{
String
redisKey
=
LOGIN_TRY_COUNT
+
RedisConst
.
DELIMITER
+
username
;
Integer
loginTryCount
=
RedisOpsUtils
.
getInt
(
redisKey
);
if
(
loginTryCount
==
null
)
{
loginTryCount
=
0
;
}
loginTryCount
++;
// 把尝试次数加入到redis中
RedisOpsUtils
.
setWithExpire
(
redisKey
,
loginTryCount
,
DATE_SECONDS
);
// 超过尝试登录次数的话,用户锁定
if
(
loginTryCount
.
equals
(
LOGIN_TRY_COUNT_MAX
))
{
RedisOpsUtils
.
setWithExpire
(
LOGIN_TRY_LOCK
+
RedisConst
.
DELIMITER
+
username
,
System
.
currentTimeMillis
(),
HOUR_SECONDS
);
}
// 超过尝试登录次数的第二阶段的话,用户锁定更长的时间
if
(
loginTryCount
>=
LOGIN_TRY_COUNT_MAX_SECOND
)
{
RedisOpsUtils
.
setWithExpire
(
LOGIN_TRY_LOCK
+
RedisConst
.
DELIMITER
+
username
,
System
.
currentTimeMillis
(),
DATE_SECONDS
);
}
}
/**
* 检查当前的IP,尝试登录的次数是否超过
*
* @param username 用户名
* @return 结果
*/
private
boolean
checkLoginTryCountLock
(
String
username
)
{
String
redisKey
=
LOGIN_TRY_LOCK
+
RedisConst
.
DELIMITER
+
username
;
return
!
RedisOpsUtils
.
checkExist
(
redisKey
);
}
/**
* Verify the username and password to log in.
* @param loginDTO
...
...
@@ -94,6 +240,9 @@ public class UserServiceImpl extends ServiceImpl<IUserMapper, UserEntity> implem
@Override
public
HttpResultResponse
userLogin
(
UserLoginDTO
loginDTO
)
{
String
username
=
loginDTO
.
getUsername
();
Integer
flag
=
loginDTO
.
getFlag
();
String
password
=
loginDTO
.
getPassword
();
...
...
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