feat(system): 加密方式调整
This commit is contained in:
@@ -63,8 +63,9 @@ public class ApiEncryptProperties {
|
|||||||
* 注意:
|
* 注意:
|
||||||
* 1. 如果是【对称加密】时,它「后端」对应的是“密钥”。对应的,「前端」也对应的也是“密钥”。
|
* 1. 如果是【对称加密】时,它「后端」对应的是“密钥”。对应的,「前端」也对应的也是“密钥”。
|
||||||
* 2. 如果是【非对称加密】时,它「后端」对应的是“公钥”。对应的,「前端」对应的是“私钥”。(重要!!!)
|
* 2. 如果是【非对称加密】时,它「后端」对应的是“公钥”。对应的,「前端」对应的是“私钥”。(重要!!!)
|
||||||
|
*
|
||||||
|
* 当前 system 模块密码加密方案不启用响应加密,因此该配置可为空。
|
||||||
*/
|
*/
|
||||||
@NotEmpty(message = "响应的加密密钥不能为空")
|
|
||||||
private String responseKey;
|
private String responseKey;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.njcn.rdms.framework.common.enums.WebFilterOrderEnum;
|
|||||||
import com.njcn.rdms.framework.encrypt.core.filter.ApiEncryptFilter;
|
import com.njcn.rdms.framework.encrypt.core.filter.ApiEncryptFilter;
|
||||||
import com.njcn.rdms.framework.web.config.WebProperties;
|
import com.njcn.rdms.framework.web.config.WebProperties;
|
||||||
import com.njcn.rdms.framework.web.core.handler.GlobalExceptionHandler;
|
import com.njcn.rdms.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
@@ -24,9 +25,10 @@ public class RdmsApiEncryptAutoConfiguration {
|
|||||||
public FilterRegistrationBean<ApiEncryptFilter> apiEncryptFilter(WebProperties webProperties,
|
public FilterRegistrationBean<ApiEncryptFilter> apiEncryptFilter(WebProperties webProperties,
|
||||||
ApiEncryptProperties apiEncryptProperties,
|
ApiEncryptProperties apiEncryptProperties,
|
||||||
RequestMappingHandlerMapping requestMappingHandlerMapping,
|
RequestMappingHandlerMapping requestMappingHandlerMapping,
|
||||||
GlobalExceptionHandler globalExceptionHandler) {
|
GlobalExceptionHandler globalExceptionHandler,
|
||||||
|
ObjectMapper objectMapper) {
|
||||||
ApiEncryptFilter filter = new ApiEncryptFilter(webProperties, apiEncryptProperties,
|
ApiEncryptFilter filter = new ApiEncryptFilter(webProperties, apiEncryptProperties,
|
||||||
requestMappingHandlerMapping, globalExceptionHandler);
|
requestMappingHandlerMapping, globalExceptionHandler, objectMapper);
|
||||||
return createFilterBean(filter, WebFilterOrderEnum.API_ENCRYPT_FILTER);
|
return createFilterBean(filter, WebFilterOrderEnum.API_ENCRYPT_FILTER);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ public @interface ApiEncrypt {
|
|||||||
*/
|
*/
|
||||||
boolean request() default true;
|
boolean request() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 需要解密的请求字段
|
||||||
|
*
|
||||||
|
* 仅在 request = true 时生效
|
||||||
|
*/
|
||||||
|
String[] requestFields() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否对响应结果进行加密,默认 true
|
* 是否对响应结果进行加密,默认 true
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package com.njcn.rdms.framework.encrypt.core.filter;
|
package com.njcn.rdms.framework.encrypt.core.filter;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import cn.hutool.crypto.asymmetric.AsymmetricDecryptor;
|
import cn.hutool.crypto.asymmetric.AsymmetricDecryptor;
|
||||||
import cn.hutool.crypto.asymmetric.KeyType;
|
import cn.hutool.crypto.asymmetric.KeyType;
|
||||||
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
||||||
@@ -14,6 +18,9 @@ import java.io.BufferedReader;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解密请求 {@link HttpServletRequestWrapper} 实现类
|
* 解密请求 {@link HttpServletRequestWrapper} 实现类
|
||||||
@@ -25,16 +32,41 @@ public class ApiDecryptRequestWrapper extends HttpServletRequestWrapper {
|
|||||||
private final byte[] body;
|
private final byte[] body;
|
||||||
|
|
||||||
public ApiDecryptRequestWrapper(HttpServletRequest request,
|
public ApiDecryptRequestWrapper(HttpServletRequest request,
|
||||||
|
ObjectMapper objectMapper,
|
||||||
|
List<String> requestFields,
|
||||||
SymmetricDecryptor symmetricDecryptor,
|
SymmetricDecryptor symmetricDecryptor,
|
||||||
AsymmetricDecryptor asymmetricDecryptor) throws IOException {
|
AsymmetricDecryptor asymmetricDecryptor) throws IOException {
|
||||||
super(request);
|
super(request);
|
||||||
// 读取 body,允许 HEX、BASE64 传输
|
if (CollUtil.isEmpty(requestFields)) {
|
||||||
String requestBody = StrUtil.utf8Str(
|
throw invalidParamException("请求解密失败,请刷新页面后重试");
|
||||||
IoUtil.readBytes(request.getInputStream(), false));
|
}
|
||||||
|
String requestBody = StrUtil.utf8Str(IoUtil.readBytes(request.getInputStream(), false));
|
||||||
|
if (StrUtil.isBlank(requestBody)) {
|
||||||
|
throw invalidParamException("请求解密失败,请刷新页面后重试");
|
||||||
|
}
|
||||||
|
|
||||||
// 解密 body
|
JsonNode requestJson;
|
||||||
body = symmetricDecryptor != null ? symmetricDecryptor.decrypt(requestBody)
|
try {
|
||||||
: asymmetricDecryptor.decrypt(requestBody, KeyType.PrivateKey);
|
requestJson = objectMapper.readTree(requestBody);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw invalidParamException("请求解密失败,请刷新页面后重试");
|
||||||
|
}
|
||||||
|
if (!(requestJson instanceof ObjectNode requestObject)) {
|
||||||
|
throw invalidParamException("请求解密失败,请刷新页面后重试");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String requestField : requestFields) {
|
||||||
|
JsonNode fieldNode = requestObject.get(requestField);
|
||||||
|
if (fieldNode == null || fieldNode.isNull() || !fieldNode.isTextual() || StrUtil.isBlank(fieldNode.asText())) {
|
||||||
|
throw invalidParamException("请求解密失败,请刷新页面后重试");
|
||||||
|
}
|
||||||
|
byte[] decryptedBytes = symmetricDecryptor != null
|
||||||
|
? symmetricDecryptor.decrypt(fieldNode.asText())
|
||||||
|
: asymmetricDecryptor.decrypt(fieldNode.asText(), KeyType.PrivateKey);
|
||||||
|
requestObject.put(requestField, StrUtil.utf8Str(decryptedBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
body = objectMapper.writeValueAsBytes(requestObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import cn.hutool.crypto.asymmetric.AsymmetricDecryptor;
|
|||||||
import cn.hutool.crypto.asymmetric.AsymmetricEncryptor;
|
import cn.hutool.crypto.asymmetric.AsymmetricEncryptor;
|
||||||
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
||||||
import cn.hutool.crypto.symmetric.SymmetricEncryptor;
|
import cn.hutool.crypto.symmetric.SymmetricEncryptor;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||||
import com.njcn.rdms.framework.common.util.object.ObjectUtils;
|
import com.njcn.rdms.framework.common.util.object.ObjectUtils;
|
||||||
import com.njcn.rdms.framework.common.util.servlet.ServletUtils;
|
import com.njcn.rdms.framework.common.util.servlet.ServletUtils;
|
||||||
@@ -26,6 +27,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||||||
import org.springframework.web.util.ServletRequestPathUtils;
|
import org.springframework.web.util.ServletRequestPathUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
||||||
|
|
||||||
@@ -43,12 +45,17 @@ import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class ApiEncryptFilter extends ApiRequestFilter {
|
public class ApiEncryptFilter extends ApiRequestFilter {
|
||||||
|
|
||||||
|
private static final String MISSING_ENCRYPT_HEADER_MESSAGE = "当前接口要求加密传输,请刷新页面后重试";
|
||||||
|
private static final String DECRYPT_FAILED_MESSAGE = "请求解密失败,请刷新页面后重试";
|
||||||
|
|
||||||
private final ApiEncryptProperties apiEncryptProperties;
|
private final ApiEncryptProperties apiEncryptProperties;
|
||||||
|
|
||||||
private final RequestMappingHandlerMapping requestMappingHandlerMapping;
|
private final RequestMappingHandlerMapping requestMappingHandlerMapping;
|
||||||
|
|
||||||
private final GlobalExceptionHandler globalExceptionHandler;
|
private final GlobalExceptionHandler globalExceptionHandler;
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
private final SymmetricDecryptor requestSymmetricDecryptor;
|
private final SymmetricDecryptor requestSymmetricDecryptor;
|
||||||
private final AsymmetricDecryptor requestAsymmetricDecryptor;
|
private final AsymmetricDecryptor requestAsymmetricDecryptor;
|
||||||
|
|
||||||
@@ -58,21 +65,25 @@ public class ApiEncryptFilter extends ApiRequestFilter {
|
|||||||
public ApiEncryptFilter(WebProperties webProperties,
|
public ApiEncryptFilter(WebProperties webProperties,
|
||||||
ApiEncryptProperties apiEncryptProperties,
|
ApiEncryptProperties apiEncryptProperties,
|
||||||
RequestMappingHandlerMapping requestMappingHandlerMapping,
|
RequestMappingHandlerMapping requestMappingHandlerMapping,
|
||||||
GlobalExceptionHandler globalExceptionHandler) {
|
GlobalExceptionHandler globalExceptionHandler,
|
||||||
|
ObjectMapper objectMapper) {
|
||||||
super(webProperties);
|
super(webProperties);
|
||||||
this.apiEncryptProperties = apiEncryptProperties;
|
this.apiEncryptProperties = apiEncryptProperties;
|
||||||
this.requestMappingHandlerMapping = requestMappingHandlerMapping;
|
this.requestMappingHandlerMapping = requestMappingHandlerMapping;
|
||||||
this.globalExceptionHandler = globalExceptionHandler;
|
this.globalExceptionHandler = globalExceptionHandler;
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "AES")) {
|
if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "AES")) {
|
||||||
this.requestSymmetricDecryptor = SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getRequestKey()));
|
this.requestSymmetricDecryptor = SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getRequestKey()));
|
||||||
this.requestAsymmetricDecryptor = null;
|
this.requestAsymmetricDecryptor = null;
|
||||||
this.responseSymmetricEncryptor = SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getResponseKey()));
|
this.responseSymmetricEncryptor = StrUtil.isNotBlank(apiEncryptProperties.getResponseKey())
|
||||||
|
? SecureUtil.aes(StrUtil.utf8Bytes(apiEncryptProperties.getResponseKey())) : null;
|
||||||
this.responseAsymmetricEncryptor = null;
|
this.responseAsymmetricEncryptor = null;
|
||||||
} else if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "RSA")) {
|
} else if (StrUtil.equalsIgnoreCase(apiEncryptProperties.getAlgorithm(), "RSA")) {
|
||||||
this.requestSymmetricDecryptor = null;
|
this.requestSymmetricDecryptor = null;
|
||||||
this.requestAsymmetricDecryptor = SecureUtil.rsa(apiEncryptProperties.getRequestKey(), null);
|
this.requestAsymmetricDecryptor = SecureUtil.rsa(apiEncryptProperties.getRequestKey(), null);
|
||||||
this.responseSymmetricEncryptor = null;
|
this.responseSymmetricEncryptor = null;
|
||||||
this.responseAsymmetricEncryptor = SecureUtil.rsa(null, apiEncryptProperties.getResponseKey());
|
this.responseAsymmetricEncryptor = StrUtil.isNotBlank(apiEncryptProperties.getResponseKey())
|
||||||
|
? SecureUtil.rsa(null, apiEncryptProperties.getResponseKey()) : null;
|
||||||
} else {
|
} else {
|
||||||
// 补充说明:如果要支持 SM2、SM4 等算法,可在此处增加对应实例的创建,并添加相应的 Maven 依赖即可。
|
// 补充说明:如果要支持 SM2、SM4 等算法,可在此处增加对应实例的创建,并添加相应的 Maven 依赖即可。
|
||||||
throw new IllegalArgumentException("不支持的加密算法:" + apiEncryptProperties.getAlgorithm());
|
throw new IllegalArgumentException("不支持的加密算法:" + apiEncryptProperties.getAlgorithm());
|
||||||
@@ -86,9 +97,10 @@ public class ApiEncryptFilter extends ApiRequestFilter {
|
|||||||
// 获取 @ApiEncrypt 注解
|
// 获取 @ApiEncrypt 注解
|
||||||
ApiEncrypt apiEncrypt = getApiEncrypt(request);
|
ApiEncrypt apiEncrypt = getApiEncrypt(request);
|
||||||
boolean requestEnable = apiEncrypt != null && apiEncrypt.request();
|
boolean requestEnable = apiEncrypt != null && apiEncrypt.request();
|
||||||
boolean responseEnable = apiEncrypt != null && apiEncrypt.response();
|
boolean responseEnable = apiEncrypt != null && apiEncrypt.response()
|
||||||
|
&& (responseSymmetricEncryptor != null || responseAsymmetricEncryptor != null);
|
||||||
String encryptHeader = request.getHeader(apiEncryptProperties.getHeader());
|
String encryptHeader = request.getHeader(apiEncryptProperties.getHeader());
|
||||||
if (!requestEnable && !responseEnable && StrUtil.isBlank(encryptHeader)) {
|
if (!requestEnable && !responseEnable) {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -97,13 +109,19 @@ public class ApiEncryptFilter extends ApiRequestFilter {
|
|||||||
if (ObjectUtils.equalsAny(HttpMethod.valueOf(request.getMethod()),
|
if (ObjectUtils.equalsAny(HttpMethod.valueOf(request.getMethod()),
|
||||||
HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE)) {
|
HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE)) {
|
||||||
try {
|
try {
|
||||||
if (StrUtil.isNotBlank(encryptHeader)) {
|
if (requestEnable) {
|
||||||
request = new ApiDecryptRequestWrapper(request,
|
if (StrUtil.isBlank(encryptHeader)) {
|
||||||
|
throw invalidParamException(MISSING_ENCRYPT_HEADER_MESSAGE);
|
||||||
|
}
|
||||||
|
request = new ApiDecryptRequestWrapper(request, objectMapper,
|
||||||
|
Arrays.asList(apiEncrypt.requestFields()),
|
||||||
requestSymmetricDecryptor, requestAsymmetricDecryptor);
|
requestSymmetricDecryptor, requestAsymmetricDecryptor);
|
||||||
} else if (requestEnable) {
|
|
||||||
throw invalidParamException("请求未包含加密标头,请检查是否正确配置了加密标头");
|
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
if (!(ex instanceof com.njcn.rdms.framework.common.exception.ServiceException)
|
||||||
|
|| !StrUtil.equals(ex.getMessage(), MISSING_ENCRYPT_HEADER_MESSAGE)) {
|
||||||
|
ex = invalidParamException(DECRYPT_FAILED_MESSAGE);
|
||||||
|
}
|
||||||
CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
|
CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
|
||||||
ServletUtils.writeJSON(response, result);
|
ServletUtils.writeJSON(response, result);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ spring:
|
|||||||
username: # Nacos 账号
|
username: # Nacos 账号
|
||||||
password: # Nacos 密码
|
password: # Nacos 密码
|
||||||
discovery: # 【配置中心】配置项
|
discovery: # 【配置中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
config: # 【注册中心】配置项
|
config: # 【注册中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
|
|
||||||
#################### 监控相关配置 ####################
|
#################### 监控相关配置 ####################
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ spring:
|
|||||||
username: # Nacos 账号
|
username: # Nacos 账号
|
||||||
password: # Nacos 密码
|
password: # Nacos 密码
|
||||||
discovery: # 【配置中心】配置项
|
discovery: # 【配置中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
config: # 【注册中心】配置项
|
config: # 【注册中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
|
|
||||||
#################### 监控相关配置 ####################
|
#################### 监控相关配置 ####################
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||||
|
import com.njcn.rdms.framework.encrypt.core.annotation.ApiEncrypt;
|
||||||
import com.njcn.rdms.framework.security.config.SecurityProperties;
|
import com.njcn.rdms.framework.security.config.SecurityProperties;
|
||||||
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
|
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import com.njcn.rdms.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
import com.njcn.rdms.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
||||||
@@ -69,6 +70,7 @@ public class AuthController {
|
|||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
@PermitAll
|
@PermitAll
|
||||||
@Operation(summary = "使用账号密码登录")
|
@Operation(summary = "使用账号密码登录")
|
||||||
|
@ApiEncrypt(response = false, requestFields = {"password"})
|
||||||
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
|
public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO) {
|
||||||
return success(authService.login(reqVO));
|
return success(authService.login(reqVO));
|
||||||
}
|
}
|
||||||
@@ -141,6 +143,7 @@ public class AuthController {
|
|||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
@PermitAll
|
@PermitAll
|
||||||
@Operation(summary = "注册用户")
|
@Operation(summary = "注册用户")
|
||||||
|
@ApiEncrypt(response = false, requestFields = {"password"})
|
||||||
public CommonResult<AuthLoginRespVO> register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
|
public CommonResult<AuthLoginRespVO> register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
|
||||||
return success(authService.register(registerReqVO));
|
return success(authService.register(registerReqVO));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
|||||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||||
import com.njcn.rdms.framework.common.pojo.PageParam;
|
import com.njcn.rdms.framework.common.pojo.PageParam;
|
||||||
import com.njcn.rdms.framework.common.pojo.PageResult;
|
import com.njcn.rdms.framework.common.pojo.PageResult;
|
||||||
|
import com.njcn.rdms.framework.encrypt.core.annotation.ApiEncrypt;
|
||||||
import com.njcn.rdms.framework.excel.core.util.ExcelUtils;
|
import com.njcn.rdms.framework.excel.core.util.ExcelUtils;
|
||||||
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportExcelVO;
|
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportExcelVO;
|
||||||
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportRespVO;
|
import com.njcn.rdms.module.system.controller.admin.user.vo.user.UserImportRespVO;
|
||||||
@@ -67,6 +68,7 @@ public class UserController {
|
|||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@Operation(summary = "新增用户")
|
@Operation(summary = "新增用户")
|
||||||
@PreAuthorize("@ss.hasPermission('system:user:create')")
|
@PreAuthorize("@ss.hasPermission('system:user:create')")
|
||||||
|
@ApiEncrypt(response = false, requestFields = {"password"})
|
||||||
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
|
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
|
||||||
Long id = userService.createUser(reqVO);
|
Long id = userService.createUser(reqVO);
|
||||||
return success(id);
|
return success(id);
|
||||||
@@ -101,6 +103,7 @@ public class UserController {
|
|||||||
@PutMapping("/update-password")
|
@PutMapping("/update-password")
|
||||||
@Operation(summary = "重置用户密码")
|
@Operation(summary = "重置用户密码")
|
||||||
@PreAuthorize("@ss.hasPermission('system:user:update-password')")
|
@PreAuthorize("@ss.hasPermission('system:user:update-password')")
|
||||||
|
@ApiEncrypt(response = false, requestFields = {"password"})
|
||||||
public CommonResult<Boolean> updateUserPassword(@Valid @RequestBody UserUpdatePasswordReqVO reqVO) {
|
public CommonResult<Boolean> updateUserPassword(@Valid @RequestBody UserUpdatePasswordReqVO reqVO) {
|
||||||
userService.updateUserPassword(reqVO.getId(), reqVO.getPassword());
|
userService.updateUserPassword(reqVO.getId(), reqVO.getPassword());
|
||||||
return success(true);
|
return success(true);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.njcn.rdms.module.system.controller.admin.user;
|
|||||||
|
|
||||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||||
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
import com.njcn.rdms.framework.common.enums.CommonStatusEnum;
|
||||||
|
import com.njcn.rdms.framework.encrypt.core.annotation.ApiEncrypt;
|
||||||
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
|
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
|
||||||
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
|
||||||
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
import com.njcn.rdms.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||||
@@ -77,6 +78,7 @@ public class UserProfileController {
|
|||||||
|
|
||||||
@PutMapping("/update-password")
|
@PutMapping("/update-password")
|
||||||
@Operation(summary = "修改用户个人密码")
|
@Operation(summary = "修改用户个人密码")
|
||||||
|
@ApiEncrypt(response = false, requestFields = {"oldPassword", "newPassword"})
|
||||||
public CommonResult<Boolean> updateUserProfilePassword(@Valid @RequestBody UserProfileUpdatePasswordReqVO reqVO) {
|
public CommonResult<Boolean> updateUserProfilePassword(@Valid @RequestBody UserProfileUpdatePasswordReqVO reqVO) {
|
||||||
userService.updateUserPassword(getLoginUserId(), reqVO);
|
userService.updateUserPassword(getLoginUserId(), reqVO);
|
||||||
return success(true);
|
return success(true);
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ spring:
|
|||||||
username: # Nacos 账号
|
username: # Nacos 账号
|
||||||
password: # Nacos 密码
|
password: # Nacos 密码
|
||||||
discovery: # 【配置中心】配置项
|
discovery: # 【配置中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
metadata:
|
metadata:
|
||||||
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
|
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
|
||||||
config: # 【注册中心】配置项
|
config: # 【注册中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
|
|
||||||
#################### 数据库相关配置 ####################
|
#################### 数据库相关配置 ####################
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ spring:
|
|||||||
username: # Nacos 账号
|
username: # Nacos 账号
|
||||||
password: # Nacos 密码
|
password: # Nacos 密码
|
||||||
discovery: # 【配置中心】配置项
|
discovery: # 【配置中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
metadata:
|
metadata:
|
||||||
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
|
version: 1.0.0 # 服务实例的版本号,可用于灰度发布
|
||||||
config: # 【注册中心】配置项
|
config: # 【注册中心】配置项
|
||||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
namespace: 1e0fcd92-49b4-4cda-b531-828c7d36fef5 # 命名空间。这里使用 dev 开发环境
|
||||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||||
|
|
||||||
#################### 数据库相关配置 ####################
|
#################### 数据库相关配置 ####################
|
||||||
|
|||||||
@@ -119,6 +119,10 @@ rdms:
|
|||||||
websocket:
|
websocket:
|
||||||
enable: true # 是否开启 WebSocket
|
enable: true # 是否开启 WebSocket
|
||||||
path: /system/ws # WebSocket 路径
|
path: /system/ws # WebSocket 路径
|
||||||
|
api-encrypt:
|
||||||
|
enable: true # 启用密码相关接口的请求解密能力
|
||||||
|
header: X-Api-Encrypt # 请求加密标记头
|
||||||
|
algorithm: RSA # 密码相关接口的请求体采用 RSA 非对称加密
|
||||||
|
request-key: 'MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC/aShtWjlpINa+ZZkgp4sbt2jA4tPCN1YjDLv5SZMHDd7q8lbkE0SOudbuSKp5P3tVCPZXowyZom5+l56AAIYCaG5OcbzeRUtB6JcvmuU9SZ008zw7z2BIzeIzMtJSGf6u8BocVeMo27bGyyh1ifUXbpKVU7V7DBLzYADAQ9Jqi0vsqrxDGDu+Zm3LpFwSOnv85pgC0d+9re57CIYynXVmTLAo+V5DedPsceNCAByRs1kUyFMwyoPNbmgjcpKbewD6laxR9GtnFR/bCzfnz8Up7ANtuHCPe7vfU1teU75ZR+/cW9t2GS1e1T/XkULRv5PH5gchSGQ1NHO4imIbv5dzAgMBAAECggEACTjSS051BKUh44N2mLWpxJiWEfD7vdg3rLGg3tZWIJlg+5XYbN2myG+YtNtIZ1YRJZwsbjV7Vm2WgD/i0Yz05+nLIrllHZpeEVtY6WC/ma/RxKrRZJpNq8RLmSbiLjV1aU1FHMdgjefkCvjfxqXyaoIXyt0BGeAPi6087AZ4fUyKVYgPyGr53RnD8+4nCDaRhZYMCv6zpb+YVF3llZZNhvK7+hDLZX0WhUgIAzStzFsPZhDfJxW8MQFB4FNtmnJ4kpInkgIAROlfVvKIwRKwoCH+sveGjYdlZR/wTYt6HQoKudG9Qx2IssUcVGFwAsCiWM+81rfBDd5pMUwzyGQ9OQKBgQDHOp7Eio4M6LaPO1Uz6Ozlp28evWBVPaU+wk50p5SQl//pF0VgDkmrrt3Wu9IppBL6VObIzjOsZJrEVHXheA/1qqOVYm/m6nel1EUAqbIqxREtw+GJPoKp3Ql1CxK6pvm/KxOhJvCDIUNCZ4in+rvsCvquF784iIbQ33ED3hWi2wKBgQD19DbAL1Y6/XHXX17t6yZJVsIijmSOo5tjeNHouOSP5emgc8i2ESaW4WPIzkgi7EJ2aertgUkwIOpunYvMWYfn6zrYNaSuvCCZF+6oIiYPPXEVZJTnzGA/KsJtHeH6xtiGuettw6RnPxXvNZibJhfLdOqQvZmRDRTXh/MiRuelSQKBgQC154IbNd7pTnmRYb0zvlK+hRfiW0rfyX9dRBBaVsBBHWedrY+8Wo9NYEZQ0ADd4F8rjeWCJzPrDZh59hwDl5oK1pixxsUhc6d3E89FAawZfQFoZddBdn/bFGSUJ14camTR9UTg+SrUr8Q3l0yhA0AeDxA/cJM5zP47LCiGPXpHzQKBgQDV00sGKiE9h7nBFBjjntvaRqLgiArEN1iQUimruZJ7x9YkuIR2RNLXuXuWyD/OnLfrWonzkcKfJP6qzC0Nq4iMB+VQstJJVyS/9B537bhI55G4l4kdPIEwaWw+kQw1iUoVVu1mr//uAtp+7ImP2L43E54Z17v6bvT/rCGkWyBogQKBgQC6pqnciYteAE5KmWnPM9LWoEorSBPCzbWCVwuja7NbVoADUPvAnUeDgvKs8KpWvL+X3eRGSZXOBqjBMsdDPBnQzr5yZCI3Mv6Svg9RxBfuWw1mF1w2GAwK1r7+6ZDwxFqRUiVUACRRJ8S1kBa+CvNWm7UFi/7V1D4UDyKKmBU6Sw=='
|
||||||
|
|
||||||
debug: false
|
debug: false
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
function Select-Option {
|
function Select-Option {
|
||||||
param(
|
param(
|
||||||
|
|||||||
Reference in New Issue
Block a user