河北安全测评整改需求

This commit is contained in:
2024-07-22 13:53:04 +08:00
parent 6fa63a7f3e
commit ec051827ac
15 changed files with 254 additions and 76 deletions

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
import com.nimbusds.jose.jwk.JWKSet; import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.RSAKey;
import com.njcn.auth.service.UserTokenService; import com.njcn.auth.service.UserTokenService;
import com.njcn.auth.utils.AuthPubUtil;
import com.njcn.common.pojo.annotation.OperateInfo; import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.constant.OperateType; import com.njcn.common.pojo.constant.OperateType;
import com.njcn.common.pojo.constant.SecurityConstants; import com.njcn.common.pojo.constant.SecurityConstants;
@@ -47,6 +48,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* @author hongawen * @author hongawen
@@ -73,7 +75,7 @@ public class AuthController extends BaseController {
@ApiIgnore @ApiIgnore
@OperateInfo(info = LogEnum.SYSTEM_COMMON, operateType = OperateType.AUTHENTICATE) @OperateInfo(info = LogEnum.SYSTEM_SERIOUS, operateType = OperateType.AUTHENTICATE)
@ApiOperation("登录认证") @ApiOperation("登录认证")
@ApiImplicitParams({ @ApiImplicitParams({
@ApiImplicitParam(name = SecurityConstants.GRANT_TYPE, defaultValue = "password", value = "授权模式", required = true), @ApiImplicitParam(name = SecurityConstants.GRANT_TYPE, defaultValue = "password", value = "授权模式", required = true),
@@ -90,14 +92,7 @@ public class AuthController extends BaseController {
public Object postAccessToken(@ApiIgnore Principal principal, @RequestParam @ApiIgnore Map<String, String> parameters) throws HttpRequestMethodNotSupportedException { public Object postAccessToken(@ApiIgnore Principal principal, @RequestParam @ApiIgnore Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
String methodDescribe = getMethodDescribe("postAccessToken"); String methodDescribe = getMethodDescribe("postAccessToken");
String username = parameters.get(SecurityConstants.USERNAME); String username = parameters.get(SecurityConstants.USERNAME);
UserStrategy data = passWordRuleFeugnClient.getUserStrategy().getData();
String onlineUserKey = SecurityConstants.TOKEN_ONLINE_PREFIX;
List<UserTokenInfo> onLineUser = (List<UserTokenInfo>) redisUtil.getLikeListAllValues(onlineUserKey);
Integer maxNum = data.getMaxNum();
if((CollectionUtil.isNotEmpty(onLineUser)?onLineUser.size():0)>=maxNum){
throw new BusinessException(UserResponseEnum.LOGIN_USER_OVERLIMIT);
}
String grantType = parameters.get(SecurityConstants.GRANT_TYPE); String grantType = parameters.get(SecurityConstants.GRANT_TYPE);
if (grantType.equalsIgnoreCase(SecurityConstants.GRANT_CAPTCHA) || grantType.equalsIgnoreCase(SecurityConstants.REFRESH_TOKEN_KEY)) { if (grantType.equalsIgnoreCase(SecurityConstants.GRANT_CAPTCHA) || grantType.equalsIgnoreCase(SecurityConstants.REFRESH_TOKEN_KEY)) {
@@ -106,6 +101,24 @@ public class AuthController extends BaseController {
//短信方式登录,将手机号赋值为用户名 //短信方式登录,将手机号赋值为用户名
username = parameters.get(SecurityConstants.PHONE); username = parameters.get(SecurityConstants.PHONE);
} }
UserStrategy data = passWordRuleFeugnClient.getUserStrategy().getData();
String onlineUserKey = SecurityConstants.TOKEN_ONLINE_PREFIX;
List<UserTokenInfo> onLineUser = (List<UserTokenInfo>) redisUtil.getLikeListAllValues(onlineUserKey);
if(CollectionUtil.isNotEmpty(onLineUser)){
String finalUsername = username;
onLineUser = onLineUser.stream().filter(item->{
String login = AuthPubUtil.getLoginByToken(item.getRefreshToken());
return !login.equals(finalUsername);
}).collect(Collectors.toList());
}
Integer maxNum = data.getMaxNum();
if((CollectionUtil.isNotEmpty(onLineUser)?onLineUser.size():0)>=maxNum){
throw new BusinessException(UserResponseEnum.LOGIN_USER_OVERLIMIT);
}
if (grantType.equalsIgnoreCase(SecurityConstants.REFRESH_TOKEN_KEY)) { if (grantType.equalsIgnoreCase(SecurityConstants.REFRESH_TOKEN_KEY)) {
//如果是刷新token需要去黑名单校验 //如果是刷新token需要去黑名单校验
userTokenService.judgeRefreshToken(parameters.get(SecurityConstants.REFRESH_TOKEN_KEY)); userTokenService.judgeRefreshToken(parameters.get(SecurityConstants.REFRESH_TOKEN_KEY));
@@ -125,6 +138,7 @@ public class AuthController extends BaseController {
} }
} }
@OperateInfo(info = LogEnum.SYSTEM_SERIOUS, operateType = OperateType.LOGOUT)
@ApiOperation("用户登出系统") @ApiOperation("用户登出系统")
@DeleteMapping("/logout") @DeleteMapping("/logout")
public HttpResult<Object> logout() { public HttpResult<Object> logout() {

View File

@@ -1,9 +1,12 @@
package com.njcn.auth.utils; package com.njcn.auth.utils;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import okhttp3.*; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.nimbusds.jose.JWSObject;
import com.njcn.common.pojo.constant.SecurityConstants;
import lombok.SneakyThrows;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -28,4 +31,13 @@ public class AuthPubUtil {
return String.join("", textList); return String.join("", textList);
} }
@SneakyThrows
public static String getLoginByToken(String token){
JWSObject jwsObject = JWSObject.parse(token);
String payload = jwsObject.getPayload().toString();
JSONObject jsonObject = JSONUtil.parseObj(payload);
return jsonObject.getStr(SecurityConstants.USER_NAME_KEY);
}
} }

View File

@@ -84,10 +84,12 @@ public class LogServiceImpl implements ILogService {
publisher.send("/userLog", PubUtils.obj2json(logInfoDTO), 2, false); publisher.send("/userLog", PubUtils.obj2json(logInfoDTO), 2, false);
//推送审计消息功能 //推送审计消息功能
if(severity!=0){ if(severity!=0){
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false); if(!logInfoDTO.getLoginName().equals(LogInfo.UNKNOWN_USER)){
//发送邮箱功能 publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
if(severity==2&&logInfoDTO.getResult()==0){ //发送邮箱功能
publisher.send("/userLogEmailPush", PubUtils.obj2json(logInfoDTO), 2, false); if(severity==2&&logInfoDTO.getResult()==0){
//publisher.send("/userLogEmailPush", PubUtils.obj2json(logInfoDTO), 2, false);
}
} }
} }
//如果存在设备日志注解,则记录设备日志 //如果存在设备日志注解,则记录设备日志
@@ -167,10 +169,12 @@ public class LogServiceImpl implements ILogService {
private void auditPush(Integer severity, LogInfoDTO logInfoDTO) { private void auditPush(Integer severity, LogInfoDTO logInfoDTO) {
//推送审计消息功能 //推送审计消息功能
if(severity !=0){ if(severity !=0){
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false); if(!logInfoDTO.getLoginName().equals(LogInfo.UNKNOWN_USER)) {
//发送邮箱功能 publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
if(severity ==2&& logInfoDTO.getResult()==0){ //发送邮箱功能
publisher.send("/userLogEmailPush", PubUtils.obj2json(logInfoDTO), 2, false); if (severity == 2 && logInfoDTO.getResult() == 0) {
//publisher.send("/userLogEmailPush", PubUtils.obj2json(logInfoDTO), 2, false);
}
} }
} }
} }

View File

@@ -3,10 +3,17 @@ package com.njcn.gateway.config;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.JsonObject;
import com.github.tocrhz.mqtt.publisher.MqttPublisher;
import com.njcn.common.pojo.constant.LogInfo;
import com.njcn.common.pojo.constant.SecurityConstants; import com.njcn.common.pojo.constant.SecurityConstants;
import com.njcn.common.pojo.dto.LogInfoDTO;
import com.njcn.common.utils.PubUtils;
import com.njcn.gateway.enums.GateWayEnum; import com.njcn.gateway.enums.GateWayEnum;
import com.njcn.gateway.security.AuthorizationManager; import com.njcn.gateway.security.AuthorizationManager;
import com.njcn.gateway.utils.ResponseUtils; import com.njcn.gateway.utils.ResponseUtils;
import com.njcn.gateway.utils.WebFluxRequestUtil;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -14,6 +21,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity;
@@ -30,6 +38,8 @@ import java.io.InputStream;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
import java.time.LocalDateTime;
import java.util.Objects;
/** /**
* @author hongawen * @author hongawen
@@ -44,6 +54,8 @@ public class ResourceServerConfig {
private final WhiteListConfig whiteListConfig; private final WhiteListConfig whiteListConfig;
private final MqttPublisher publisher;
@Bean @Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
@@ -75,7 +87,31 @@ public class ResourceServerConfig {
@Bean @Bean
ServerAccessDeniedHandler accessDeniedHandler() { ServerAccessDeniedHandler accessDeniedHandler() {
return (exchange, denied) -> Mono.defer(() -> Mono.just(exchange.getResponse())) return (exchange, denied) -> Mono.defer(() -> Mono.just(exchange.getResponse()))
.flatMap(response -> ResponseUtils.writeErrorInfo(response, GateWayEnum.NO_AUTHORIZATION)); .flatMap(response -> {
ServerHttpRequest request = exchange.getRequest();
JSONObject jsonObject = WebFluxRequestUtil.getJwtPayload(request);
String loginName = jsonObject.get("user_name").toString();
String userName = jsonObject.get("nickname").toString();
String userIndex = jsonObject.get("userIndex").toString();
String ip = WebFluxRequestUtil.getRealIp(request);
LogInfoDTO logInfoDTO = new LogInfoDTO(
loginName,
userName,
ip,
"越权访问",
"越权访问",
0,
"当前用户无该接口访问权限:"+request.getPath().toString(),
2,
1,
"",
userIndex,
LocalDateTime.now()
);
publisher.send("/userLog", PubUtils.obj2json(logInfoDTO), 2, false);
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
return ResponseUtils.writeErrorInfo(response, GateWayEnum.NO_AUTHORIZATION);
});
} }
/** /**
@@ -84,7 +120,30 @@ public class ResourceServerConfig {
@Bean @Bean
ServerAuthenticationEntryPoint authenticationEntryPoint() { ServerAuthenticationEntryPoint authenticationEntryPoint() {
return (exchange, e) -> Mono.defer(() -> Mono.just(exchange.getResponse())) return (exchange, e) -> Mono.defer(() -> Mono.just(exchange.getResponse()))
.flatMap(response -> ResponseUtils.writeErrorInfo(response, GateWayEnum.ACCESS_TOKEN_EXPIRE_JWT)); .flatMap(response -> {
ServerHttpRequest request = exchange.getRequest();
JSONObject jsonObject = WebFluxRequestUtil.getJwtPayload(request);
if(Objects.isNull(jsonObject)){
String ip = WebFluxRequestUtil.getRealIp(request);
LogInfoDTO logInfoDTO = new LogInfoDTO(
ip,
ip,
ip,
"越权访问",
"越权访问",
0,
"异常token访问:"+request.getPath().toString(),
2,
1,
"",
ip,
LocalDateTime.now()
);
publisher.send("/userLog", PubUtils.obj2json(logInfoDTO), 2, false);
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
}
return ResponseUtils.writeErrorInfo(response, GateWayEnum.ACCESS_TOKEN_EXPIRE_JWT);
});
} }
/** /**

View File

@@ -0,0 +1,52 @@
package com.njcn.gateway.utils;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.nimbusds.jose.JWSObject;
import com.njcn.common.pojo.constant.LogInfo;
import com.njcn.common.pojo.constant.SecurityConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
@Slf4j
public class WebFluxRequestUtil {
/**
* HttpServletRequest获取头中存储的IP地址
*/
public static String getRealIp(ServerHttpRequest request) {
String ip = request.getURI().getHost();
return StrUtil.isBlank(ip) ? LogInfo.UNKNOWN_IP : ip;
}
/**
* ServerHttpRequest获取在网关中存储的用户token元信息
*/
public static JSONObject getJwtPayload(ServerHttpRequest request) {
JSONObject jsonObject = null;
HttpHeaders headers = request.getHeaders();
try {
if (CollectionUtil.isNotEmpty(headers.get("authorization"))) {
String token = headers.get("authorization").get(0);
token = token.replace(SecurityConstants.AUTHORIZATION_PREFIX, Strings.EMPTY);
JWSObject jwsObject = JWSObject.parse(token);
String payload = jwsObject.getPayload().toString();
jsonObject = JSONUtil.parseObj(payload);
}
} catch (Exception e) {
log.error("解码网关中心传递的请求头中内容异常,异常为:{}", e.getMessage());
e.printStackTrace();
}
return jsonObject;
}
}

View File

@@ -224,20 +224,20 @@ whitelist:
- /system-boot/dictType/dictDataCache - /system-boot/dictType/dictDataCache
- /system-boot/file/** - /system-boot/file/**
- /system-boot/area/** - /system-boot/area/**
- /advance-boot/** #- /advance-boot/**
- /device-boot/** #- /device-boot/**
#- /system-boot/** #- /system-boot/**
#- /harmonic-boot/** #- /harmonic-boot/**
#- /energy-boot/** #- /energy-boot/**
#- /event-boot/** #- /event-boot/**
#- /quality-boot/** #- /quality-boot/**
#- /harmonic-prepare/** #- /harmonic-prepare/**
- /process-boot/** #- /process-boot/**
- /bpm-boot/** #- /bpm-boot/**
- /system-boot/** #- /system-boot/**
- /supervision-boot/** #- /supervision-boot/**
- /user-boot/** #- /user-boot/**
- /harmonic-boot/** #- /harmonic-boot/**
- /user-boot/user/listAllUserByDeptId - /user-boot/user/listAllUserByDeptId
- /IndexAnalysis/** - /IndexAnalysis/**
mqtt: mqtt:

View File

@@ -33,6 +33,9 @@ public class AuditParam {
@ApiModelProperty("操作类型") @ApiModelProperty("操作类型")
private String operateType; private String operateType;
@ApiModelProperty("结果")
private Integer result;
@ApiModelProperty("页码") @ApiModelProperty("页码")
@NotNull(message = "页码不可为空") @NotNull(message = "页码不可为空")
@Range(min = 1,message = "页码必须大于0") @Range(min = 1,message = "页码必须大于0")

View File

@@ -37,11 +37,11 @@ public class ConfigParam {
*/ */
@ApiModelProperty("审计日志大小MB") @ApiModelProperty("审计日志大小MB")
@NotNull(message = "审计日志大小不可为空") @NotNull(message = "审计日志大小不可为空")
@Min(value = 0,message = "审计日志大小不能小于0") @Min(value = 1024,message = "审计日志大小不能小于1024M")
private BigDecimal logSize; private BigDecimal logSize;
/** /**
* 审计日志大小 * 审计日志保留时间
*/ */
@ApiModelProperty("审计日志存储时间1-6个月默认3个月") @ApiModelProperty("审计日志存储时间1-6个月默认3个月")
@Min(value = 1,message = "审计日志保留时间不能小于1") @Min(value = 1,message = "审计日志保留时间不能小于1")

View File

@@ -26,6 +26,7 @@ import com.njcn.common.pojo.constant.LogInfo;
import com.njcn.common.pojo.constant.OperateType; import com.njcn.common.pojo.constant.OperateType;
import com.njcn.common.pojo.constant.SecurityConstants; import com.njcn.common.pojo.constant.SecurityConstants;
import com.njcn.common.pojo.dto.UserTokenInfo; import com.njcn.common.pojo.dto.UserTokenInfo;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException; import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.oss.constant.OssPath; import com.njcn.oss.constant.OssPath;
import com.njcn.redis.utils.RedisUtil; import com.njcn.redis.utils.RedisUtil;
@@ -34,9 +35,11 @@ import com.njcn.system.excel.UserLogExcel;
import com.njcn.system.mapper.AuditMapper; import com.njcn.system.mapper.AuditMapper;
import com.njcn.system.mapper.UserLogMapper; import com.njcn.system.mapper.UserLogMapper;
import com.njcn.system.pojo.param.AuditParam; import com.njcn.system.pojo.param.AuditParam;
import com.njcn.system.pojo.po.Config;
import com.njcn.system.pojo.po.UserLog; import com.njcn.system.pojo.po.UserLog;
import com.njcn.system.pojo.vo.*; import com.njcn.system.pojo.vo.*;
import com.njcn.system.service.AuditService; import com.njcn.system.service.AuditService;
import com.njcn.system.service.IConfigService;
import com.njcn.user.api.UserFeignClient; import com.njcn.user.api.UserFeignClient;
import com.njcn.user.pojo.po.User; import com.njcn.user.pojo.po.User;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -62,6 +65,8 @@ import java.time.temporal.TemporalAdjusters;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.njcn.common.pojo.constant.LogInfo.UNKNOWN_USER;
/** /**
* @version 1.0.0 * @version 1.0.0
* @author: chenchao * @author: chenchao
@@ -81,28 +86,38 @@ public class AuditServiceImpl extends ServiceImpl<UserLogMapper, UserLog> implem
private final UserFeignClient userFeignClient; private final UserFeignClient userFeignClient;
@Value("${clear.num}") @Value("${clear.num}")
private Integer clearHistoryLog; private Integer clearHistoryLog;
private IConfigService iConfigService;
@Override @Override
public Page<AuditLogVO> getAuditLog(AuditParam auditParam) { public Page<AuditLogVO> getAuditLog(AuditParam auditParam) {
List<AuditLogVO> auditLogVOS = new ArrayList<>(); List<AuditLogVO> auditLogVOS = new ArrayList<>();
Page<UserLog> info = this.page(new Page<>(auditParam.getPageNum(), auditParam.getPageSize()), new LambdaQueryWrapper<UserLog>() LambdaQueryWrapper<UserLog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
.and(StrUtil.isNotBlank(auditParam.getLoginName()), qw -> lambdaQueryWrapper
//如果Objects.equals(auditParam.getOperateType(), OperateType.AUTHENTICATE)则是用户登陆信息查询页面loginname可模糊匹配IpCreateTime .between(UserLog::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(auditParam.getSearchBeginTime())),
qw.like(UserLog::getLoginName, auditParam.getLoginName()).or(Objects.equals(auditParam.getOperateType(), OperateType.AUTHENTICATE)).like( DateUtil.endOfDay(DateUtil.parse(auditParam.getSearchEndTime())))
UserLog::getIp, auditParam.getLoginName() .ne(UserLog::getLoginName,UNKNOWN_USER)
).or(Objects.equals(auditParam.getOperateType(), OperateType.AUTHENTICATE)).like( .orderByDesc(UserLog::getCreateTime);
UserLog::getCreateTime, auditParam.getLoginName()
))
.ne(UserLog::getLoginName, LogInfo.UNKNOWN_USER) if (StrUtil.isNotBlank(auditParam.getLoginName())) {
.ne(UserLog::getLoginName, "") lambdaQueryWrapper.eq(UserLog::getLoginName, auditParam.getLoginName());
.ne(UserLog::getOperate, LogInfo.UNKNOWN_OPERATE) }
.eq(auditParam.getType() != null, UserLog::getType, auditParam.getType()) if (StrUtil.isNotBlank(auditParam.getOperateType())) {
.eq(StrUtil.isNotBlank(auditParam.getOperateType()), UserLog::getOperateType, auditParam.getOperateType()) lambdaQueryWrapper.eq(UserLog::getOperateType, auditParam.getOperateType());
.ge(StrUtil.isNotBlank(auditParam.getSearchBeginTime()), UserLog::getCreateTime, DateUtil.beginOfDay(DateUtil.parse(auditParam.getSearchBeginTime()))) }
.le(StrUtil.isNotBlank(auditParam.getSearchEndTime()), UserLog::getCreateTime, DateUtil.endOfDay(DateUtil.parse(auditParam.getSearchEndTime()))) if (Objects.nonNull(auditParam.getType())) {
.orderByDesc(UserLog::getCreateTime) lambdaQueryWrapper.eq(UserLog::getType, auditParam.getType());
); }
if (Objects.nonNull(auditParam.getResult())) {
lambdaQueryWrapper.eq(UserLog::getResult, auditParam.getResult());
}
Page<UserLog> info = this.page(new Page<>(auditParam.getPageNum(), auditParam.getPageSize()), lambdaQueryWrapper);
Page<AuditLogVO> page = BeanUtil.copyProperties(info, Page.class); Page<AuditLogVO> page = BeanUtil.copyProperties(info, Page.class);
if (CollUtil.isNotEmpty(info.getRecords())) { if (CollUtil.isNotEmpty(info.getRecords())) {
for (UserLog userLog : info.getRecords()) { for (UserLog userLog : info.getRecords()) {
@@ -148,8 +163,11 @@ public class AuditServiceImpl extends ServiceImpl<UserLogMapper, UserLog> implem
throw new BusinessException(AuditLogEnum.MULTIPLE_CLICKS_LOGFILEWRITER); throw new BusinessException(AuditLogEnum.MULTIPLE_CLICKS_LOGFILEWRITER);
} }
redisUtil.saveByKey("logFileWriter", "1"); redisUtil.saveByKey("logFileWriter", "1");
Config config = iConfigService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getState, DataStateEnum.ENABLE.getCode()));
LocalDateTime nowDate = LocalDateTime.now(); LocalDateTime nowDate = LocalDateTime.now();
LocalDateTime agoDate = nowDate.minusMonths(6).with(TemporalAdjusters.firstDayOfMonth()); LocalDateTime agoDate = nowDate.minusMonths(config.getLogTime()).with(TemporalAdjusters.firstDayOfMonth());
String date = agoDate.format(DateTimeFormatter.ISO_LOCAL_DATE); String date = agoDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
//结束时间 //结束时间
String endTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH_mm_ss").format(nowDate); String endTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH_mm_ss").format(nowDate);
@@ -258,7 +276,7 @@ public class AuditServiceImpl extends ServiceImpl<UserLogMapper, UserLog> implem
public void doAfterAllAnalysed(AnalysisContext analysisContext) { public void doAfterAllAnalysed(AnalysisContext analysisContext) {
} }
}).sheet().doRead(); }).sheet().doRead();
if(CollUtil.isNotEmpty(userLogs)){ if (CollUtil.isNotEmpty(userLogs)) {
// 执行批量插入 // 执行批量插入
saveLogsBatch(userLogs, 1500); saveLogsBatch(userLogs, 1500);
} }
@@ -365,13 +383,13 @@ public class AuditServiceImpl extends ServiceImpl<UserLogMapper, UserLog> implem
public LogParamVO saveLogParam() { public LogParamVO saveLogParam() {
LogParamVO logParamVO = new LogParamVO(); LogParamVO logParamVO = new LogParamVO();
List<UserLog> userLogs = auditMapper.selectUserLog(); List<UserLog> userLogs = auditMapper.selectUserLog();
List<ValuePO> loginNameList = userLogs.stream().map(UserLog::getLoginName).distinct().map(temp->{ List<ValuePO> loginNameList = userLogs.stream().map(UserLog::getLoginName).distinct().map(temp -> {
ValuePO valuePO = new ValuePO(); ValuePO valuePO = new ValuePO();
valuePO.setValue(temp); valuePO.setValue(temp);
return valuePO; return valuePO;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
List<ValuePO> operateTypeList = userLogs.stream().map(UserLog::getOperateType).distinct().map(temp->{ List<ValuePO> operateTypeList = userLogs.stream().map(UserLog::getOperateType).distinct().map(temp -> {
ValuePO valuePO = new ValuePO(); ValuePO valuePO = new ValuePO();
valuePO.setValue(temp); valuePO.setValue(temp);
return valuePO; return valuePO;

View File

@@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
/** /**
@@ -29,25 +30,34 @@ public class PassWordRuleParam {
@NotNull(message = "会话超时时间(分钟)不可为空") @NotNull(message = "会话超时时间(分钟)不可为空")
private Integer sessionTime; private Integer sessionTime;
@ApiModelProperty(name = "minPasswordLength",value = "密码最小长度") @ApiModelProperty(name = "sessionRefreshTime",value = "*会话刷新时间(分钟)")
@NotNull(message = "密码最小长度不可为空") @NotNull(message = "会话刷新时间(分钟)不可为空")
private Integer minPasswordLength; private Integer sessionRefreshTime;
@ApiModelProperty(name = "passwordExpirationDays",value = "密码超期天数") @ApiModelProperty(name = "passwordExpirationDays",value = "密码超期天数")
@NotNull(message = "密码超期天数不可为空") @NotNull(message = "密码超期天数不可为空")
private Integer passwordExpirationDays; private Integer passwordExpirationDays;
@ApiModelProperty(name = "mixedCheckFlag",value = "密码符号混合校验(0:否1是)") /* @ApiModelProperty(name = "mixedCheckFlag",value = "密码符号混合校验(0:否1是)")
@NotNull(message = "密码符号混合校验不可为空") //@NotNull(message = "密码符号混合校验不可为空")
private Integer mixedCheckFlag; private Integer mixedCheckFlag;
@ApiModelProperty(name = "doubleCheckFlag",value = "密码重复校验(0:否1是)") @ApiModelProperty(name = "doubleCheckFlag",value = "密码重复校验(0:否1是)")
@NotNull(message = "密码重复校验不可为空") //@NotNull(message = "密码重复校验不可为空")
private Integer doubleCheckFlag; private Integer doubleCheckFlag;
@ApiModelProperty(name = "mixedCheckFlag",value = "密码大小写混合校验(0:否1是)" ) @ApiModelProperty(name = "mixedCheckFlag",value = "密码大小写混合校验(0:否1是)" )
@NotNull(message = "密码大小写混合校验不可为空") //@NotNull(message = "密码大小写混合校验不可为空")
private Integer mixedCaseCheckFlag; private Integer mixedCaseCheckFlag;*/
@ApiModelProperty(name = "maxUseUser",value = "大于0" )
@NotNull(message = "最大并发用户不可为空")
@Min(value = 1,message = "最大并发数需要大于0")
private Integer maxUseUser;
@NotNull(message = "账号长时间未登录休眠期(天)")
@Min(value = 1,message = "账号长时间未登录休眠期应大于0")
private Integer sleepDay;
} }

View File

@@ -68,4 +68,6 @@ public class UserStrategy extends BaseEntity {
*/ */
private Integer state; private Integer state;
} }

View File

@@ -132,7 +132,7 @@ public class FunctionController extends BaseController {
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS,list,methodDescribe); return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS,list,methodDescribe);
} }
@OperateInfo(operateType = OperateType.UPDATE) @OperateInfo(operateType = OperateType.UPDATE,info = LogEnum.SYSTEM_MEDIUM)
@PostMapping("/assignFunctionByRoleIndexes") @PostMapping("/assignFunctionByRoleIndexes")
@ApiOperation("角色分配菜单") @ApiOperation("角色分配菜单")
@ApiImplicitParam(name = "roleFunctionComponent", value = "角色信息", required = true) @ApiImplicitParam(name = "roleFunctionComponent", value = "角色信息", required = true)

View File

@@ -65,7 +65,7 @@ public class PassWordRuleController extends BaseController {
} }
@OperateInfo(info = LogEnum.BUSINESS_COMMON) @OperateInfo(info = LogEnum.SYSTEM_SERIOUS)
@ApiOperation("解锁超级管理员") @ApiOperation("解锁超级管理员")
@RequestMapping(value = "/unlockRoot", method = RequestMethod.POST) @RequestMapping(value = "/unlockRoot", method = RequestMethod.POST)
public HttpResult<Boolean> unlockRoot() { public HttpResult<Boolean> unlockRoot() {

View File

@@ -373,7 +373,7 @@ public class UserController extends BaseController {
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, publicKey, methodDescribe); return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, publicKey, methodDescribe);
} }
@OperateInfo(operateType = OperateType.UPDATE) @OperateInfo(operateType = OperateType.UPDATE,info = LogEnum.SYSTEM_SERIOUS)
@PutMapping("/updateUserLoginErrorTimes/{loginName}") @PutMapping("/updateUserLoginErrorTimes/{loginName}")
@ApiOperation("更新用户登录认证密码错误次数") @ApiOperation("更新用户登录认证密码错误次数")
@ApiImplicitParam(name = "loginName", value = "登录名", required = true) @ApiImplicitParam(name = "loginName", value = "登录名", required = true)
@@ -391,7 +391,7 @@ public class UserController extends BaseController {
* *
* @param password 确认密码 * @param password 确认密码
*/ */
@OperateInfo @OperateInfo(operateType = OperateType.AUTHENTICATE,info = LogEnum.SYSTEM_SERIOUS)
@GetMapping("/passwordConfirm") @GetMapping("/passwordConfirm")
@ApiOperation("密码二次确认") @ApiOperation("密码二次确认")
@ApiImplicitParam(name = "password", value = "确认密码") @ApiImplicitParam(name = "password", value = "确认密码")

View File

@@ -3,8 +3,10 @@ package com.njcn.user.service.impl;
import com.njcn.common.pojo.enums.common.DataStateEnum; import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.redis.utils.RedisUtil; import com.njcn.redis.utils.RedisUtil;
import com.njcn.user.pojo.param.PassWordRuleParam; import com.njcn.user.pojo.param.PassWordRuleParam;
import com.njcn.user.pojo.po.AuthClient;
import com.njcn.user.pojo.po.User; import com.njcn.user.pojo.po.User;
import com.njcn.user.pojo.po.UserStrategy; import com.njcn.user.pojo.po.UserStrategy;
import com.njcn.user.service.IAuthClientService;
import com.njcn.user.service.IUserService; import com.njcn.user.service.IUserService;
import com.njcn.user.service.IUserStrategyService; import com.njcn.user.service.IUserStrategyService;
import com.njcn.user.service.PassWordRuleService; import com.njcn.user.service.PassWordRuleService;
@@ -24,6 +26,8 @@ import org.springframework.transaction.annotation.Transactional;
public class PassWordRuleServiceImpl implements PassWordRuleService { public class PassWordRuleServiceImpl implements PassWordRuleService {
private final IUserStrategyService iUserStrategyService; private final IUserStrategyService iUserStrategyService;
private final IAuthClientService iAuthClientService;
private final RedisUtil redisUtil; private final RedisUtil redisUtil;
private final IUserService userService; private final IUserService userService;
@@ -36,13 +40,14 @@ public class PassWordRuleServiceImpl implements PassWordRuleService {
.set(UserStrategy::getLimitPwdTimes,passWordRuleParam.getErrorsCount()) .set(UserStrategy::getLimitPwdTimes,passWordRuleParam.getErrorsCount())
.set(UserStrategy::getLimitPwdDate,passWordRuleParam.getPasswordExpirationDays()) .set(UserStrategy::getLimitPwdDate,passWordRuleParam.getPasswordExpirationDays())
.set(UserStrategy::getLockPwdCheck,passWordRuleParam.getReleaseTime()) .set(UserStrategy::getLockPwdCheck,passWordRuleParam.getReleaseTime())
.set(UserStrategy::getLockPwdTime,passWordRuleParam.getSessionTime()).update(); .set(UserStrategy::getMaxNum,passWordRuleParam.getMaxUseUser())
.set(UserStrategy::getSleep,passWordRuleParam.getSleepDay())
redisUtil.saveByKey("mixedCheckFlag",passWordRuleParam.getMixedCheckFlag()); .update();
redisUtil.saveByKey("doubleCheckFlag",passWordRuleParam.getDoubleCheckFlag());
redisUtil.saveByKey("mixedCaseCheckFlag",passWordRuleParam.getMixedCaseCheckFlag());
redisUtil.saveByKey("minPasswordLength",passWordRuleParam.getMinPasswordLength());
iAuthClientService.lambdaUpdate()
.set(AuthClient::getRefreshTokenValidity,passWordRuleParam.getSessionRefreshTime())
.set(AuthClient::getAccessTokenValidity,passWordRuleParam.getSessionTime())
.update();
return true; return true;
} }
@@ -53,14 +58,13 @@ public class PassWordRuleServiceImpl implements PassWordRuleService {
passWordRuleParam.setErrorsCount(userStrategy.getLimitPwdTimes()); passWordRuleParam.setErrorsCount(userStrategy.getLimitPwdTimes());
passWordRuleParam.setReleaseTime(userStrategy.getLockPwdCheck()); passWordRuleParam.setReleaseTime(userStrategy.getLockPwdCheck());
passWordRuleParam.setSessionTime(userStrategy.getLockPwdTime());
passWordRuleParam.setMinPasswordLength((Integer)(redisUtil.getObjectByKey("minPasswordLength")));
passWordRuleParam.setPasswordExpirationDays(userStrategy.getLimitPwdDate()); passWordRuleParam.setPasswordExpirationDays(userStrategy.getLimitPwdDate());
passWordRuleParam.setMixedCheckFlag((Integer)(redisUtil.getObjectByKey("mixedCheckFlag"))); passWordRuleParam.setMaxUseUser(userStrategy.getMaxNum());
passWordRuleParam.setDoubleCheckFlag((Integer)(redisUtil.getObjectByKey("doubleCheckFlag"))); passWordRuleParam.setSleepDay(userStrategy.getSleep());
passWordRuleParam.setMixedCaseCheckFlag((Integer)(redisUtil.getObjectByKey("mixedCaseCheckFlag")));
AuthClient authClient = iAuthClientService.lambdaQuery().last(" limit 1").one();
passWordRuleParam.setSessionTime(authClient.getAccessTokenValidity());
passWordRuleParam.setSessionRefreshTime(authClient.getRefreshTokenValidity());
return passWordRuleParam; return passWordRuleParam;
} }