🔒 过滤用户密码在访问日志和操作日志中的存储
This commit is contained in:
@@ -10,6 +10,9 @@ import com.hccake.ballcat.admin.oauth.util.SecurityUtils;
|
||||
import com.hccake.ballcat.commom.log.access.handler.AccessLogHandler;
|
||||
import com.hccake.ballcat.commom.log.constant.LogConstant;
|
||||
import com.hccake.ballcat.commom.log.util.LogUtils;
|
||||
import com.hccake.ballcat.common.core.desensite.DesensitizationHandler;
|
||||
import com.hccake.ballcat.common.core.desensite.DesensitizationHandlerHolder;
|
||||
import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant;
|
||||
import com.hccake.ballcat.common.core.util.IPUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -20,6 +23,9 @@ import org.springframework.web.servlet.HandlerMapping;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -39,6 +45,17 @@ public class AdminAccessLogHandler implements AccessLogHandler<AdminAccessLog> {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 需要脱敏记录的参数
|
||||
*/
|
||||
private final List<String> needDesensitizeParams = Arrays.asList("password", "pass", "passConfirm");
|
||||
|
||||
/**
|
||||
* 脱敏处理器
|
||||
*/
|
||||
private final DesensitizationHandler desensitizationHandler = DesensitizationHandlerHolder.TYPE_MAPS
|
||||
.get(DesensitizationTypeConstant.ENCRYPTED_PASSWORD);
|
||||
|
||||
/**
|
||||
* 生产一个日志
|
||||
* @return accessLog
|
||||
@@ -53,6 +70,7 @@ public class AdminAccessLogHandler implements AccessLogHandler<AdminAccessLog> {
|
||||
Object matchingPatternAttr = request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
|
||||
String matchingPattern = matchingPatternAttr == null ? "" : String.valueOf(matchingPatternAttr);
|
||||
// @formatter:off
|
||||
String uri = URLUtil.getPath(request.getRequestURI());
|
||||
AdminAccessLog adminAccessLog = new AdminAccessLog()
|
||||
.setTraceId(MDC.get(LogConstant.TRACE_ID))
|
||||
.setCreateTime(LocalDateTime.now())
|
||||
@@ -60,30 +78,25 @@ public class AdminAccessLogHandler implements AccessLogHandler<AdminAccessLog> {
|
||||
.setIp(IPUtil.getIpAddr(request))
|
||||
.setMethod(request.getMethod())
|
||||
.setUserAgent(request.getHeader("user-agent"))
|
||||
.setUri(URLUtil.getPath(request.getRequestURI()))
|
||||
.setUri(uri)
|
||||
.setMatchingPattern(matchingPattern)
|
||||
.setErrorMsg(Optional.ofNullable(myThrowable).map(Throwable::getMessage).orElse(""))
|
||||
.setHttpStatus(response.getStatus());
|
||||
// @formatter:on
|
||||
|
||||
// 参数获取
|
||||
String params = "";
|
||||
try {
|
||||
params = objectMapper.writeValueAsString(request.getParameterMap());
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
log.error("[prodLog],参数获取序列化异常", e);
|
||||
}
|
||||
String params = getParams(request);
|
||||
adminAccessLog.setReqParams(params);
|
||||
|
||||
// 非文件上传请求,记录body
|
||||
if (!LogUtils.isMultipartContent(request)) {
|
||||
// 非文件上传请求,记录body,用户改密时不记录body
|
||||
// TODO 使用注解控制此次请求是否记录body,更方便个性化定制
|
||||
if (!LogUtils.isMultipartContent(request) && "/sysuser/pass/{userId}".equals(uri)) {
|
||||
adminAccessLog.setReqBody(LogUtils.getRequestBody(request));
|
||||
}
|
||||
|
||||
// 只记录响应头为 application/json 的返回数据
|
||||
// 后台日志对于分页数据请求,不记录返回值
|
||||
if (!request.getRequestURI().endsWith("/page") && response.getContentType() != null
|
||||
if (!uri.endsWith("/page") && response.getContentType() != null
|
||||
&& response.getContentType().contains(APPLICATION_JSON)) {
|
||||
adminAccessLog.setResult(LogUtils.getResponseBody(request, response));
|
||||
}
|
||||
@@ -97,6 +110,30 @@ public class AdminAccessLogHandler implements AccessLogHandler<AdminAccessLog> {
|
||||
return adminAccessLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取参数信息
|
||||
* @param request 请求信息
|
||||
* @return 请求参数
|
||||
*/
|
||||
public String getParams(HttpServletRequest request) {
|
||||
String params;
|
||||
try {
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
for (String paramKey : needDesensitizeParams) {
|
||||
String[] values = parameterMap.get(paramKey);
|
||||
if (values != null && values.length != 0) {
|
||||
parameterMap.put(paramKey, new String[] { desensitizationHandler.handle(values[0]) });
|
||||
}
|
||||
}
|
||||
params = objectMapper.writeValueAsString(parameterMap);
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
params = "记录参数异常";
|
||||
log.error("[prodLog],参数获取序列化异常", e);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录日志
|
||||
* @param accessLog 访问日志
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.hccake.ballcat.admin.modules.sys.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.hccake.ballcat.admin.constants.SysUserConst;
|
||||
import com.hccake.ballcat.admin.modules.sys.model.dto.SysUserDTO;
|
||||
import com.hccake.ballcat.admin.modules.sys.model.dto.SysUserPassDTO;
|
||||
import com.hccake.ballcat.admin.modules.sys.model.dto.SysUserScope;
|
||||
import com.hccake.ballcat.admin.modules.sys.model.entity.SysRole;
|
||||
import com.hccake.ballcat.admin.modules.sys.model.entity.SysUser;
|
||||
@@ -25,6 +25,7 @@ import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@@ -42,6 +43,7 @@ import java.util.List;
|
||||
* @author hccake 2020-09-24 20:16:15
|
||||
*/
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestController
|
||||
@RequestMapping("/sysuser")
|
||||
@Api(value = "sysuser", tags = "用户管理模块")
|
||||
@@ -161,12 +163,11 @@ public class SysUserController {
|
||||
@ApiOperation(value = "修改系统用户密码", notes = "修改系统用户密码")
|
||||
@UpdateOperationLogging(msg = "修改系统用户密码")
|
||||
@PreAuthorize("@per.hasPermission('sys:sysuser:pass')")
|
||||
public R<?> updateUserPass(@PathVariable Integer userId, String pass, String confirm) {
|
||||
if (StrUtil.isBlank(pass) || StrUtil.isBlank(confirm) || !pass.equals(confirm)) {
|
||||
public R<?> updateUserPass(@PathVariable Integer userId, @RequestBody SysUserPassDTO sysUserPassDTO) {
|
||||
if (!sysUserPassDTO.getPass().equals(sysUserPassDTO.getConfirmPass())) {
|
||||
return R.failed(SystemResultCode.BAD_REQUEST, "错误的密码!");
|
||||
}
|
||||
|
||||
return sysUserService.updateUserPass(userId, pass) ? R.ok()
|
||||
return sysUserService.updateUserPass(userId, sysUserPassDTO.getPass()) ? R.ok()
|
||||
: R.failed(BaseResultCode.UPDATE_DATABASE_ERROR, "修改用户密码失败!");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.hccake.ballcat.admin.modules.sys.model.dto;
|
||||
|
||||
import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant;
|
||||
import com.hccake.ballcat.common.core.desensite.JsonDesensitize;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -21,6 +23,7 @@ public class SysUserDTO {
|
||||
/**
|
||||
* 前端传入密码
|
||||
*/
|
||||
@JsonDesensitize(type = DesensitizationTypeConstant.ENCRYPTED_PASSWORD)
|
||||
@ApiModelProperty(value = "前端传入密码")
|
||||
private String pass;
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.hccake.ballcat.admin.modules.sys.model.dto;
|
||||
|
||||
import com.hccake.ballcat.common.core.desensite.DesensitizationTypeConstant;
|
||||
import com.hccake.ballcat.common.core.desensite.JsonDesensitize;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 用户密码传输DTO,字段序列化时忽略,防止记录
|
||||
*
|
||||
* @author Hccake 2021/1/22
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
public class SysUserPassDTO {
|
||||
|
||||
/**
|
||||
* 前端传入密码
|
||||
*/
|
||||
@NotBlank(message = "The password cannot be empty!")
|
||||
@JsonDesensitize(type = DesensitizationTypeConstant.ENCRYPTED_PASSWORD)
|
||||
@ApiModelProperty(value = "前端输入密码")
|
||||
private String pass;
|
||||
|
||||
/**
|
||||
* 前端确认密码
|
||||
*/
|
||||
@NotBlank(message = "The confirm password cannot be empty!")
|
||||
@JsonDesensitize(type = DesensitizationTypeConstant.ENCRYPTED_PASSWORD)
|
||||
@ApiModelProperty(value = "前端确认密码")
|
||||
private String confirmPass;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user