Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
6f0a002e
提交
6f0a002e
authored
3月 18, 2019
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
后端:增加用户访问日志
上级
532daf62
显示空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
476 行增加
和
2 行删除
+476
-2
MVCConfiguration.java
...ocoder/mall/user/application/config/MVCConfiguration.java
+8
-2
UserAccessLogInterceptor.java
...r/mall/user/sdk/interceptor/UserAccessLogInterceptor.java
+78
-0
UserSecurityInterceptor.java
...er/mall/user/sdk/interceptor/UserSecurityInterceptor.java
+7
-0
UserAccessLogService.java
...n/iocoder/mall/user/service/api/UserAccessLogService.java
+11
-0
UserAccessLogAddDTO.java
...ocoder/mall/user/service/api/dto/UserAccessLogAddDTO.java
+132
-0
UserAccessLogConvert.java
...va/cn/iocoder/mall/user/convert/UserAccessLogConvert.java
+18
-0
UserAccessLogMapper.java
...in/java/cn/iocoder/mall/user/dao/UserAccessLogMapper.java
+11
-0
UserAccessLogDO.java
...java/cn/iocoder/mall/user/dataobject/UserAccessLogDO.java
+133
-0
UserAccessLogServiceImpl.java
...n/iocoder/mall/user/service/UserAccessLogServiceImpl.java
+57
-0
UserAccessLogMapper.xml
...ce-impl/src/main/resources/mapper/UserAccessLogMapper.xml
+21
-0
没有找到文件。
user/user-application/src/main/java/cn/iocoder/mall/user/application/config/MVCConfiguration.java
浏览文件 @
6f0a002e
...
@@ -2,6 +2,7 @@ package cn.iocoder.mall.user.application.config;
...
@@ -2,6 +2,7 @@ package cn.iocoder.mall.user.application.config;
import
cn.iocoder.common.framework.config.GlobalExceptionHandler
;
import
cn.iocoder.common.framework.config.GlobalExceptionHandler
;
import
cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor
;
import
cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor
;
import
cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor
;
import
cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor
;
import
cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
...
@@ -18,13 +19,18 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
...
@@ -18,13 +19,18 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public
class
MVCConfiguration
implements
WebMvcConfigurer
{
public
class
MVCConfiguration
implements
WebMvcConfigurer
{
@Autowired
@Autowired
private
UserSecurityInterceptor
securityInterceptor
;
private
UserSecurityInterceptor
userSecurityInterceptor
;
@Autowired
private
UserAccessLogInterceptor
userAccessLogInterceptor
;
@Autowired
@Autowired
private
AdminSecurityInterceptor
adminSecurityInterceptor
;
private
AdminSecurityInterceptor
adminSecurityInterceptor
;
@Override
@Override
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
public
void
addInterceptors
(
InterceptorRegistry
registry
)
{
registry
.
addInterceptor
(
securityInterceptor
).
addPathPatterns
(
"/users/**"
);
// 只拦截我们定义的接口
// 用户
registry
.
addInterceptor
(
userAccessLogInterceptor
).
addPathPatterns
(
"/users/**"
);
registry
.
addInterceptor
(
userSecurityInterceptor
).
addPathPatterns
(
"/users/**"
);
// 只拦截我们定义的接口
// 管理员
registry
.
addInterceptor
(
adminSecurityInterceptor
).
addPathPatterns
(
"/admins/**"
);
// 只拦截我们定义的接口
registry
.
addInterceptor
(
adminSecurityInterceptor
).
addPathPatterns
(
"/admins/**"
);
// 只拦截我们定义的接口
}
}
...
...
user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java
0 → 100644
浏览文件 @
6f0a002e
package
cn
.
iocoder
.
mall
.
user
.
sdk
.
interceptor
;
import
cn.iocoder.common.framework.util.HttpUtil
;
import
cn.iocoder.mall.user.service.api.UserAccessLogService
;
import
cn.iocoder.mall.user.service.api.dto.UserAccessLogAddDTO
;
import
com.alibaba.dubbo.config.annotation.Reference
;
import
com.alibaba.fastjson.JSON
;
import
org.apache.commons.lang3.exception.ExceptionUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.servlet.handler.HandlerInterceptorAdapter
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.util.Date
;
/**
* 访问日志拦截器
*/
@Component
public
class
UserAccessLogInterceptor
extends
HandlerInterceptorAdapter
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
getClass
());
/**
* 开始时间
*/
private
static
final
ThreadLocal
<
Date
>
START_TIME
=
new
ThreadLocal
<>();
/**
* 管理员编号
*/
private
static
final
ThreadLocal
<
Integer
>
USER_ID
=
new
ThreadLocal
<>();
@Reference
private
UserAccessLogService
userAccessLogService
;
@Override
public
boolean
preHandle
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Object
handler
)
{
// 记录当前时间
START_TIME
.
set
(
new
Date
());
return
true
;
}
@Override
public
void
afterCompletion
(
HttpServletRequest
request
,
HttpServletResponse
response
,
Object
handler
,
Exception
ex
)
{
UserAccessLogAddDTO
accessLog
=
new
UserAccessLogAddDTO
();
try
{
accessLog
.
setUserId
(
USER_ID
.
get
());
if
(
accessLog
.
getUserId
()
==
null
)
{
accessLog
.
setUserId
(
UserAccessLogAddDTO
.
USER_ID_NULL
);
}
accessLog
.
setUri
(
request
.
getRequestURI
());
// TODO 提升:如果想要优化,可以使用 Swagger 的 @ApiOperation 注解。
accessLog
.
setQueryString
(
HttpUtil
.
buildQueryString
(
request
));
accessLog
.
setMethod
(
request
.
getMethod
());
accessLog
.
setUserAgent
(
HttpUtil
.
getUserAgent
(
request
));
accessLog
.
setIp
(
HttpUtil
.
getIp
(
request
));
accessLog
.
setStartTime
(
START_TIME
.
get
());
accessLog
.
setResponseTime
((
int
)
(
System
.
currentTimeMillis
()
-
accessLog
.
getStartTime
().
getTime
()));
// 默认响应时间设为0
userAccessLogService
.
addUserAccessLog
(
accessLog
);
// TODO 提升:暂时不考虑 ELK 的方案。而是基于 MySQL 存储。如果访问日志比较多,需要定期归档。
}
catch
(
Throwable
th
)
{
logger
.
error
(
"[afterCompletion][插入管理员访问日志({}) 发生异常({})"
,
JSON
.
toJSONString
(
accessLog
),
ExceptionUtils
.
getRootCauseMessage
(
th
));
}
finally
{
clear
();
}
}
public
static
void
setUserId
(
Integer
userId
)
{
USER_ID
.
set
(
userId
);
}
public
static
void
clear
()
{
START_TIME
.
remove
();
USER_ID
.
remove
();
}
}
user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserSecurityInterceptor.java
浏览文件 @
6f0a002e
...
@@ -40,6 +40,13 @@ public class UserSecurityInterceptor extends HandlerInterceptorAdapter {
...
@@ -40,6 +40,13 @@ public class UserSecurityInterceptor extends HandlerInterceptorAdapter {
// 添加到 SecurityContext
// 添加到 SecurityContext
UserSecurityContext
context
=
new
UserSecurityContext
(
authentication
.
getUserId
());
UserSecurityContext
context
=
new
UserSecurityContext
(
authentication
.
getUserId
());
UserSecurityContextHolder
.
setContext
(
context
);
UserSecurityContextHolder
.
setContext
(
context
);
// 同时也记录管理员编号到 AdminAccessLogInterceptor 中。因为:
// AdminAccessLogInterceptor 需要在 AdminSecurityInterceptor 之前执行,这样记录的访问日志才健全
// AdminSecurityInterceptor 执行后,会移除 AdminSecurityContext 信息,这就导致 AdminAccessLogInterceptor 无法获得管理员编号
// 因此,这里需要进行记录
if
(
authentication
.
getUserId
()
!=
null
)
{
UserAccessLogInterceptor
.
setUserId
(
authentication
.
getUserId
());
}
}
}
// 校验是否需要已授权
// 校验是否需要已授权
HandlerMethod
method
=
(
HandlerMethod
)
handler
;
HandlerMethod
method
=
(
HandlerMethod
)
handler
;
...
...
user/user-service-api/src/main/java/cn/iocoder/mall/user/service/api/UserAccessLogService.java
0 → 100644
浏览文件 @
6f0a002e
package
cn
.
iocoder
.
mall
.
user
.
service
.
api
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.mall.user.service.api.dto.UserAccessLogAddDTO
;
public
interface
UserAccessLogService
{
CommonResult
<
Boolean
>
addUserAccessLog
(
UserAccessLogAddDTO
userAccessLogAddDTO
);
}
\ No newline at end of file
user/user-service-api/src/main/java/cn/iocoder/mall/user/service/api/dto/UserAccessLogAddDTO.java
0 → 100644
浏览文件 @
6f0a002e
package
cn
.
iocoder
.
mall
.
user
.
service
.
api
.
dto
;
import
javax.validation.constraints.NotNull
;
import
java.util.Date
;
/**
* 用户访问日志添加 DTO
*/
public
class
UserAccessLogAddDTO
{
/**
* 用户编号 - 空
*/
public
static
final
Integer
USER_ID_NULL
=
0
;
/**
* 用户编号.
*
* 当用户为空时,该值为0
*/
@NotNull
(
message
=
"用户编号不能为空"
)
private
Integer
userId
;
/**
* 访问地址
*/
@NotNull
(
message
=
"访问地址不能为空"
)
private
String
uri
;
/**
* 参数
*/
@NotNull
(
message
=
"请求参数不能为空"
)
private
String
queryString
;
/**
* http 方法
*/
@NotNull
(
message
=
"http 请求方法不能为空"
)
private
String
method
;
/**
* User Agent
*/
@NotNull
(
message
=
"User-Agent 不能为空"
)
private
String
userAgent
;
/**
* ip
*/
@NotNull
(
message
=
"ip 不能为空"
)
private
String
ip
;
/**
* 请求时间
*/
@NotNull
(
message
=
"请求时间不能为空"
)
private
Date
startTime
;
/**
* 响应时长 -- 毫秒级
*/
@NotNull
(
message
=
"响应时长不能为空"
)
private
Integer
responseTime
;
public
Integer
getUserId
()
{
return
userId
;
}
public
UserAccessLogAddDTO
setUserId
(
Integer
userId
)
{
this
.
userId
=
userId
;
return
this
;
}
public
String
getUri
()
{
return
uri
;
}
public
UserAccessLogAddDTO
setUri
(
String
uri
)
{
this
.
uri
=
uri
;
return
this
;
}
public
String
getQueryString
()
{
return
queryString
;
}
public
UserAccessLogAddDTO
setQueryString
(
String
queryString
)
{
this
.
queryString
=
queryString
;
return
this
;
}
public
String
getMethod
()
{
return
method
;
}
public
UserAccessLogAddDTO
setMethod
(
String
method
)
{
this
.
method
=
method
;
return
this
;
}
public
String
getUserAgent
()
{
return
userAgent
;
}
public
UserAccessLogAddDTO
setUserAgent
(
String
userAgent
)
{
this
.
userAgent
=
userAgent
;
return
this
;
}
public
String
getIp
()
{
return
ip
;
}
public
UserAccessLogAddDTO
setIp
(
String
ip
)
{
this
.
ip
=
ip
;
return
this
;
}
public
Date
getStartTime
()
{
return
startTime
;
}
public
UserAccessLogAddDTO
setStartTime
(
Date
startTime
)
{
this
.
startTime
=
startTime
;
return
this
;
}
public
Integer
getResponseTime
()
{
return
responseTime
;
}
public
UserAccessLogAddDTO
setResponseTime
(
Integer
responseTime
)
{
this
.
responseTime
=
responseTime
;
return
this
;
}
}
\ No newline at end of file
user/user-service-impl/src/main/java/cn/iocoder/mall/user/convert/UserAccessLogConvert.java
0 → 100644
浏览文件 @
6f0a002e
package
cn
.
iocoder
.
mall
.
user
.
convert
;
import
cn.iocoder.mall.user.dataobject.UserAccessLogDO
;
import
cn.iocoder.mall.user.service.api.dto.UserAccessLogAddDTO
;
import
org.mapstruct.Mapper
;
import
org.mapstruct.Mappings
;
import
org.mapstruct.factory.Mappers
;
@Mapper
public
interface
UserAccessLogConvert
{
UserAccessLogConvert
INSTANCE
=
Mappers
.
getMapper
(
UserAccessLogConvert
.
class
);
@Mappings
({})
UserAccessLogDO
convert
(
UserAccessLogAddDTO
adminAccessLogAddDTO
);
}
\ No newline at end of file
user/user-service-impl/src/main/java/cn/iocoder/mall/user/dao/UserAccessLogMapper.java
0 → 100644
浏览文件 @
6f0a002e
package
cn
.
iocoder
.
mall
.
user
.
dao
;
import
cn.iocoder.mall.user.dataobject.UserAccessLogDO
;
import
org.springframework.stereotype.Repository
;
@Repository
public
interface
UserAccessLogMapper
{
void
insert
(
UserAccessLogDO
entity
);
}
user/user-service-impl/src/main/java/cn/iocoder/mall/user/dataobject/UserAccessLogDO.java
0 → 100644
浏览文件 @
6f0a002e
package
cn
.
iocoder
.
mall
.
user
.
dataobject
;
import
cn.iocoder.common.framework.dataobject.BaseDO
;
import
java.util.Date
;
/**
* 用户访问日志 DO
*/
public
class
UserAccessLogDO
extends
BaseDO
{
/**
* 编号
*/
private
Integer
id
;
/**
* 用户编号.
*
* 当用户编号为空时,该值为0
*/
private
Integer
userId
;
/**
* 访问地址
*/
private
String
uri
;
/**
* 参数
*/
private
String
queryString
;
/**
* http 方法
*/
private
String
method
;
/**
* userAgent
*/
private
String
userAgent
;
/**
* ip
*/
private
String
ip
;
/**
* 请求时间
*/
private
Date
startTime
;
/**
* 响应时长 -- 毫秒级
*/
private
Integer
responseTime
;
public
Integer
getId
()
{
return
id
;
}
public
UserAccessLogDO
setId
(
Integer
id
)
{
this
.
id
=
id
;
return
this
;
}
public
Integer
getUserId
()
{
return
userId
;
}
public
UserAccessLogDO
setUserId
(
Integer
userId
)
{
this
.
userId
=
userId
;
return
this
;
}
public
String
getUri
()
{
return
uri
;
}
public
UserAccessLogDO
setUri
(
String
uri
)
{
this
.
uri
=
uri
;
return
this
;
}
public
String
getQueryString
()
{
return
queryString
;
}
public
UserAccessLogDO
setQueryString
(
String
queryString
)
{
this
.
queryString
=
queryString
;
return
this
;
}
public
String
getMethod
()
{
return
method
;
}
public
UserAccessLogDO
setMethod
(
String
method
)
{
this
.
method
=
method
;
return
this
;
}
public
String
getUserAgent
()
{
return
userAgent
;
}
public
UserAccessLogDO
setUserAgent
(
String
userAgent
)
{
this
.
userAgent
=
userAgent
;
return
this
;
}
public
String
getIp
()
{
return
ip
;
}
public
UserAccessLogDO
setIp
(
String
ip
)
{
this
.
ip
=
ip
;
return
this
;
}
public
Date
getStartTime
()
{
return
startTime
;
}
public
UserAccessLogDO
setStartTime
(
Date
startTime
)
{
this
.
startTime
=
startTime
;
return
this
;
}
public
Integer
getResponseTime
()
{
return
responseTime
;
}
public
UserAccessLogDO
setResponseTime
(
Integer
responseTime
)
{
this
.
responseTime
=
responseTime
;
return
this
;
}
}
\ No newline at end of file
user/user-service-impl/src/main/java/cn/iocoder/mall/user/service/UserAccessLogServiceImpl.java
0 → 100644
浏览文件 @
6f0a002e
package
cn
.
iocoder
.
mall
.
user
.
service
;
import
cn.iocoder.common.framework.util.StringUtil
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.mall.user.convert.UserAccessLogConvert
;
import
cn.iocoder.mall.user.dao.UserAccessLogMapper
;
import
cn.iocoder.mall.user.dataobject.UserAccessLogDO
;
import
cn.iocoder.mall.user.service.api.UserAccessLogService
;
import
cn.iocoder.mall.user.service.api.dto.UserAccessLogAddDTO
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.Date
;
@Service
@com
.
alibaba
.
dubbo
.
config
.
annotation
.
Service
(
validation
=
"true"
)
public
class
UserAccessLogServiceImpl
implements
UserAccessLogService
{
/**
* 请求参数最大长度。
*/
private
static
final
Integer
QUERY_STRING_MAX_LENGTH
=
4096
;
/**
* 请求地址最大长度。
*/
private
static
final
Integer
URI_MAX_LENGTH
=
4096
;
/**
* User-Agent 最大长度。
*/
private
static
final
Integer
USER_AGENT_MAX_LENGTH
=
1024
;
@Autowired
private
UserAccessLogMapper
userAccessLogMapper
;
@Override
public
CommonResult
<
Boolean
>
addUserAccessLog
(
UserAccessLogAddDTO
userAccessLogAddDTO
)
{
// 创建 UserAccessLogDO
UserAccessLogDO
accessLog
=
UserAccessLogConvert
.
INSTANCE
.
convert
(
userAccessLogAddDTO
);
accessLog
.
setCreateTime
(
new
Date
());
// 截取最大长度
if
(
accessLog
.
getUri
().
length
()
>
URI_MAX_LENGTH
)
{
accessLog
.
setUri
(
StringUtil
.
substring
(
accessLog
.
getUri
(),
URI_MAX_LENGTH
));
}
if
(
accessLog
.
getQueryString
().
length
()
>
QUERY_STRING_MAX_LENGTH
)
{
accessLog
.
setQueryString
(
StringUtil
.
substring
(
accessLog
.
getQueryString
(),
QUERY_STRING_MAX_LENGTH
));
}
if
(
accessLog
.
getUserAgent
().
length
()
>
USER_AGENT_MAX_LENGTH
)
{
accessLog
.
setUserAgent
(
StringUtil
.
substring
(
accessLog
.
getUserAgent
(),
USER_AGENT_MAX_LENGTH
));
}
// 插入
userAccessLogMapper
.
insert
(
accessLog
);
// 返回成功
return
CommonResult
.
success
(
true
);
}
}
\ No newline at end of file
user/user-service-impl/src/main/resources/mapper/UserAccessLogMapper.xml
0 → 100644
浏览文件 @
6f0a002e
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"cn.iocoder.mall.user.dao.UserAccessLogMapper"
>
<!--<sql id="FIELDS">-->
<!--id, username, nickname, password, status,-->
<!--create_time-->
<!--</sql>-->
<insert
id=
"insert"
parameterType=
"UserAccessLogDO"
useGeneratedKeys=
"true"
keyColumn=
"id"
keyProperty=
"id"
>
INSERT INTO user_access_log (
user_id, uri, query_string, method, user_agent,
ip, start_time, response_time, create_time
) VALUES (
#{userId}, #{uri}, #{queryString}, #{method}, #{userAgent},
#{ip}, #{startTime}, #{responseTime}, #{createTime}
)
</insert>
</mapper>
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论