河北安全测评整改需求
This commit is contained in:
@@ -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() {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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){
|
||||||
|
if(!logInfoDTO.getLoginName().equals(LogInfo.UNKNOWN_USER)){
|
||||||
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
|
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
|
||||||
//发送邮箱功能
|
//发送邮箱功能
|
||||||
if(severity==2&&logInfoDTO.getResult()==0){
|
if(severity==2&&logInfoDTO.getResult()==0){
|
||||||
publisher.send("/userLogEmailPush", PubUtils.obj2json(logInfoDTO), 2, false);
|
//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){
|
||||||
|
if(!logInfoDTO.getLoginName().equals(LogInfo.UNKNOWN_USER)) {
|
||||||
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
|
publisher.send("/userLogPush", PubUtils.obj2json(logInfoDTO), 2, false);
|
||||||
//发送邮箱功能
|
//发送邮箱功能
|
||||||
if (severity == 2 && logInfoDTO.getResult() == 0) {
|
if (severity == 2 && logInfoDTO.getResult() == 0) {
|
||||||
publisher.send("/userLogEmailPush", PubUtils.obj2json(logInfoDTO), 2, false);
|
//publisher.send("/userLogEmailPush", PubUtils.obj2json(logInfoDTO), 2, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -82,27 +87,37 @@ public class AuditServiceImpl extends ServiceImpl<UserLogMapper, UserLog> implem
|
|||||||
|
|
||||||
@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可模糊匹配Ip,CreateTime
|
.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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,4 +68,6 @@ public class UserStrategy extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
private Integer state;
|
private Integer state;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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 = "确认密码")
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user