siqLogin(AppEnterpriseLoginBo bo) {
JSONObject userInfo = siqLoginInfo(bo);
- log.info("---> 深i企登录用户信息:{}", userInfo);
+// log.info("---> 深i企登录用户信息:{}", userInfo);
return doSiqLoginWithLock(userInfo);
}
@@ -134,22 +135,15 @@ public class AppEnterpriseLoginServiceImpl implements IAppEnterpriseLoginService
try {
locked = lock.tryLock(5, 60*5, TimeUnit.SECONDS);
if (!locked) {
- log.info("用户正在登录中,用户信息:{}", userInfo.toJSONString());
throw new BaseException("用户正在登录中,请稍后再试");
}
- log.info("---> 登入锁 key: {}", lockKey);
-
EnterpriseUser newUser = saveOrUpdateEnterpriseUser(userInfo);
- log.info("---> newUser: {}", newUser);
EnterpriseInformation enterpriseInformation = addSiqUserCompany(userInfo, newUser);
- log.info("---> enterpriseInformation: {}", enterpriseInformation);
-
if (newUser != null && enterpriseInformation != null) {
createUserEnterpriseRef(newUser.getUserId(), enterpriseInformation);
}
String token = generateToken(newUser, enterpriseInformation);
- log.info("---> token: {}", token);
return buildLoginResult(newUser, enterpriseInformation, token);
} catch (BaseException e) {
throw e;
@@ -220,7 +214,6 @@ public class AppEnterpriseLoginServiceImpl implements IAppEnterpriseLoginService
EnterpriseUser existUser = enterpriseUserMapper.selectOne(queryWrapper);
Long userId;
- log.info("===> existUser: {}", existUser);
if (existUser == null) {
log.info("企业用户不存在,执行新增操作: userName={}, userType={}", loginName, userType);
newUser = buildEnterpriseUser(userInfo, userType);
@@ -259,7 +252,7 @@ public class AppEnterpriseLoginServiceImpl implements IAppEnterpriseLoginService
user.setDeptId(UserConstants.DEFAULT_DEPT);
// 设置默认密码(MD5加盐加密)
- String defaultPassword = UserConstants.DEFAULT_PASSWORD;
+ String defaultPassword = RandomUtil.randomNumbers(8);
user.setPassword(DigestUtil.md5Hex(user.getLoginName() + defaultPassword + user.getSalt()));
// 账号状态:正常
@@ -553,7 +546,7 @@ public class AppEnterpriseLoginServiceImpl implements IAppEnterpriseLoginService
// 调试:检查 Token 是否成功存储到 Redis
long timeout = StpUtil.getTokenTimeout();
log.info("生成token成功: userId={}, token={}, timeout={}秒, platformType={}", user.getUserId(), token, timeout, loginUser.getPlatformType());
- log.info("Token session key: login:token:{}", token);
+// log.info("Token session key: login:token:{}", token);
return token;
}
diff --git a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/MssqApiServiceImpl.java b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/MssqApiServiceImpl.java
index b115cb41..a0ba5580 100644
--- a/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/MssqApiServiceImpl.java
+++ b/zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/MssqApiServiceImpl.java
@@ -52,7 +52,7 @@ public class MssqApiServiceImpl implements IMssqApiService {
//请求类型
mssqAddOrder.setInvokingServiceRequestMethod("POST");
String s = JSONObject.toJSONString(mssqAddOrder);
- log.info("民生诉求token:{}",JSONObject.toJSONString(mssqToken));
+// log.info("民生诉求token:{}",JSONObject.toJSONString(mssqToken));
log.info("民生诉求工单新增,上传参数:{}",s);
JSONObject serviceJsonData = ServiceInvocation.httpRequestForInterface(mssqUrl + "/api/API_YX/handlerProcess/channelAddOrder",
mssqAddOrder.getInvokingServiceRequestMethod(), s, appId, mssqToken.getGatewayRtime(), mssqToken.getGatewaySig());
@@ -79,14 +79,11 @@ public class MssqApiServiceImpl implements IMssqApiService {
// log.info("民生诉求获取token接口:{}",jsonObject);
if (jsonObjectBody != null) {
String accessToken = jsonObjectBody.getString("access_token");
- log.info("民生诉求获取token:{}",accessToken);
// 3.在获得服务调用秘钥access_token后,根据自己的appKey使用AES解密算法对返回值进行解密,最终获取签名密钥secretKey
String secretKey = ServiceInvocation.gatewayAesDecode(appKey, accessToken);
- log.info("民生诉求获取secretKey:{}",secretKey);
// 4.获取本地签名
String sign = gatewaySignEncode(appId, secretKey, currTime);
mssqBaseDomain.setAccessToken(accessToken);
- log.info("民生诉求获取sign:{}",sign);
//签名
mssqBaseDomain.setGatewaySig(sign);
}
@@ -206,19 +203,14 @@ public class MssqApiServiceImpl implements IMssqApiService {
String tokenSign = gatewaySignEncode(appId, appKey, currTime);
// 2.调用获取token接口
JSONObject jsonObject = httpRequest(mssqUrl + "/auth/token", "POST", "", hcpAppId, hcpTimestamp, hcpSign);
- log.info("民生诉求获取auth:{}",jsonObject.toJSONString());
JSONObject jsonObjectBody = JSONObject.parseObject(jsonObject.getString("body"));
-// log.info("民生诉求获取token接口:{}",jsonObject);
if (jsonObjectBody != null) {
String accessToken = jsonObjectBody.getString("access_token");
- log.info("民生诉求获取token:{}",accessToken);
// 3.在获得服务调用秘钥access_token后,根据自己的appKey使用AES解密算法对返回值进行解密,最终获取签名密钥secretKey
String secretKey = ServiceInvocation.gatewayAesDecode(appKey, accessToken);
- log.info("民生诉求获取secretKey:{}",secretKey);
// 4.获取本地签名
String sign = gatewaySignEncode(appId, secretKey, currTime);
mssqBaseDomain.setAccessToken(accessToken);
- log.info("民生诉求获取sign:{}",sign);
//签名
mssqBaseDomain.setGatewaySig(sign);
}
diff --git a/zdxt-web-server/zdxt-admin-web-server/Dockerfile b/zdxt-web-server/zdxt-admin-web-server/Dockerfile
index 4a043d40..4307a80a 100644
--- a/zdxt-web-server/zdxt-admin-web-server/Dockerfile
+++ b/zdxt-web-server/zdxt-admin-web-server/Dockerfile
@@ -9,6 +9,10 @@ RUN mkdir -p /ruoyi/server/logs \
/ruoyi/server/temp \
/ruoyi/skywalking/agent
+RUN groupadd -r appuser && useradd -r -g appuser -d /ruoyi/server -s /sbin/nologin appuser \
+ && chown -R appuser:appuser /ruoyi/server \
+ && chown -R appuser:appuser /ruoyi/skywalking
+
WORKDIR /ruoyi/server
ENV SERVER_PORT=8080 SNAIL_PORT=28080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
@@ -19,6 +23,10 @@ EXPOSE ${SNAIL_PORT}
ADD ./target/zdxt-admin.jar ./app.jar
+RUN chown appuser:appuser /ruoyi/server/app.jar
+
+USER appuser
+
SHELL ["/bin/bash", "-c"]
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml
index a3280f98..674a2f27 100644
--- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml
+++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml
@@ -284,10 +284,6 @@ justauth:
client-secret: 1f7d08**********5b7**********29e
redirect-uri: ${justauth.address}/social-callback?source=gitea
-#security:
-# excludes:
-# - /**
-
#深i企对接密钥 测试环境
siq:
#正式
@@ -340,6 +336,10 @@ srnwg:
paasToken: ENC(VfUgR5OXHJcKvBBfq/2ysuNPH6I7tCCeWHYSzXKicGChlMiw9mVPGD51naX9w42E)
#市认证数据加密字符
secretKey: ENC(xWBA5VwT23j14A8+6I15HCerJvo3zaRxzVE2xc0i7wZ7wq/SCflOEkHCc8wwdi0KHkDGjKIoHhs=)
+ # RSA 公钥
+ rsa-public-key: ENC(待用Jasypt加密后的公钥密文)
+ # RSA 私钥
+ rsa-private-key: ENC(待用Jasypt加密后的私钥密文)
# #测试
# url: ENC(jFwf6bYIMn+FOtbCkyPr0r+TBOPrp84tNotl912ilUZy2e9Y8cbH3uDQ5jtr6SAa)
# systemCode: ENC(ECOnqNVVPmCmnqhde6tsS5JEQYPtlmCv)
diff --git a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml
index a6bbd538..1002b60f 100644
--- a/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml
+++ b/zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-prod.yml
@@ -7,19 +7,6 @@ zdxt:
url-prefix: /profile
demo_enabled: false
---- # 监控中心配置
-spring.boot.admin.client:
- # 增加客户端开关
- enabled: false
- url: http://localhost:9090/admin
- instance:
- service-host-type: IP
- metadata:
- username: ${spring.boot.admin.client.username}
- userpassword: ${spring.boot.admin.client.password}
- username: @monitor.username@
- password: @monitor.password@
-
--- # snail-job 配置
snail-job:
enabled: false
diff --git a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/AppEnterpriseLoginControllerTest.java b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/AppEnterpriseLoginControllerTest.java
deleted file mode 100644
index 6994f5fb..00000000
--- a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/AppEnterpriseLoginControllerTest.java
+++ /dev/null
@@ -1,301 +0,0 @@
-//package com.zdxt.rest.test;
-//
-//import cn.dev33.satoken.context.mock.SaTokenContextMockUtil;
-//import org.dromara.ZdxtAdminApplication;
-//import org.junit.jupiter.api.*;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-//import org.springframework.boot.test.context.SpringBootTest;
-//import org.springframework.http.MediaType;
-//import org.springframework.test.web.servlet.MockMvc;
-//import org.springframework.test.web.servlet.MvcResult;
-//
-//import java.nio.charset.StandardCharsets;
-//
-//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-//import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-//
-///**
-// * AppEnterpriseLoginController 企业端-用户登录接口测试
-// *
-// * 覆盖以下接口:
-// * 1. POST /app-ent/login/siqLogin - 深i企用户登录
-// *
-// *
-// * 注意:此测试需要配置真实的深i企接口地址,或在测试环境中 Mock 相关服务
-// *
-// *
-// * @author zdxt
-// */
-//@SpringBootTest(classes = ZdxtAdminApplication.class)
-//@AutoConfigureMockMvc
-//@DisplayName("AppEnterpriseLoginController 企业端-用户登录接口测试")
-//@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
-//public class AppEnterpriseLoginControllerTest {
-//
-// @Autowired
-// private MockMvc mockMvc;
-//
-// private static final String BASE_URL = "/app-ent/login";
-// private static final String TEST_CLIENT_ID = "e5cd7e4891bf95d1d19206ce24a7b32e";
-//
-// @BeforeEach
-// public void setUp() {
-// SaTokenContextMockUtil.setMockContext();
-// }
-//
-// @AfterEach
-// public void tearDown() {
-// SaTokenContextMockUtil.clearContext();
-// }
-//
-// // ==================== siqLogin 接口测试 ====================
-//
-// @DisplayName("深i企登录 - 正常请求(需要有效的授权码)")
-// @Test
-// @Order(1)
-// public void testSiqLoginSuccess() throws Exception {
-// String requestBody = "{\"code\":\"test_authorization_code\"}";
-//
-// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andReturn();
-//
-// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
-// System.out.println("深i企登录接口响应: " + responseBody);
-//
-// if (responseBody.contains("\"code\":200")) {
-// Assertions.assertTrue(responseBody.contains("token"), "返回数据应包含 token");
-// Assertions.assertTrue(responseBody.contains("userId"), "返回数据应包含 userId");
-// Assertions.assertTrue(responseBody.contains("userName"), "返回数据应包含 userName");
-// Assertions.assertTrue(responseBody.contains("enterpriseId"), "返回数据应包含 enterpriseId");
-// Assertions.assertTrue(responseBody.contains("enterpriseName"), "返回数据应包含 enterpriseName");
-// System.out.println("深i企登录成功,返回了完整的用户和企业信息");
-// } else {
-// System.out.println("深i企登录失败(可能由于授权码无效或深i企接口未配置): " + responseBody);
-// }
-// }
-//
-// @DisplayName("深i企登录 - 缺少授权码参数应返回失败")
-// @Test
-// @Order(2)
-// public void testSiqLoginMissingCode() throws Exception {
-// String requestBody = "{}";
-//
-// mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andExpect(jsonPath("$.code").value(500));
-//
-// System.out.println("缺少授权码参数返回失败测试成功");
-// }
-//
-// @DisplayName("深i企登录 - 空授权码应返回失败")
-// @Test
-// @Order(3)
-// public void testSiqLoginEmptyCode() throws Exception {
-// String requestBody = "{\"code\":\"\"}";
-//
-// mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andExpect(jsonPath("$.code").value(500));
-//
-// System.out.println("空授权码返回失败测试成功");
-// }
-//
-// @DisplayName("深i企登录 - 无效授权码应返回失败")
-// @Test
-// @Order(4)
-// public void testSiqLoginInvalidCode() throws Exception {
-// String requestBody = "{\"code\":\"invalid_code_12345\"}";
-//
-// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andReturn();
-//
-// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
-//
-// if (responseBody.contains("\"code\":500")) {
-// System.out.println("无效授权码返回失败测试成功");
-// } else {
-// System.out.println("注意:无效授权码未返回预期错误,响应: " + responseBody);
-// }
-// }
-//
-// @DisplayName("深i企登录 - 验证返回数据结构完整性")
-// @Test
-// @Order(5)
-// public void testSiqLoginResponseStructure() throws Exception {
-// String requestBody = "{\"code\":\"test_code\"}";
-//
-// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andReturn();
-//
-// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
-// System.out.println("验证返回数据结构响应: " + responseBody);
-//
-// if (responseBody.contains("\"code\":200")) {
-// Assertions.assertTrue(responseBody.contains("\"data\""), "返回数据应包含 data 字段");
-//
-// String data = extractDataJson(responseBody);
-// if (data != null) {
-// Assertions.assertTrue(data.contains("token"), "data 中应包含 token");
-// Assertions.assertTrue(data.contains("userId"), "data 中应包含 userId");
-// Assertions.assertTrue(data.contains("userName"), "data 中应包含 userName");
-// Assertions.assertTrue(data.contains("loginName"), "data 中应包含 loginName");
-// Assertions.assertTrue(data.contains("phonenumber"), "data 中应包含 phonenumber");
-// Assertions.assertTrue(data.contains("enterpriseId"), "data 中应包含 enterpriseId");
-// Assertions.assertTrue(data.contains("enterpriseName"), "data 中应包含 enterpriseName");
-// Assertions.assertTrue(data.contains("enterpriseNumber"), "data 中应包含 enterpriseNumber");
-// System.out.println("返回数据结构完整,包含所有必需字段");
-// }
-// } else {
-// System.out.println("登录失败,无法验证数据结构");
-// }
-// }
-//
-// @DisplayName("深i企登录 - 重复登录应能正常处理(同一授权码多次调用)")
-// @Test
-// @Order(6)
-// public void testSiqLoginDuplicateCall() throws Exception {
-// String requestBody = "{\"code\":\"test_code\"}";
-//
-// for (int i = 1; i <= 3; i++) {
-// System.out.println("========== 第 " + i + " 次调用深i企登录 ==========");
-//
-// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andReturn();
-//
-// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
-// System.out.println("第 " + i + " 次调用响应: " + responseBody);
-//
-// Thread.sleep(1000);
-// }
-//
-// System.out.println("========== 重复登录测试完成 ==========");
-// }
-//
-// @DisplayName("深i企登录 - 验证 Token 格式")
-// @Test
-// @Order(7)
-// public void testSiqLoginTokenFormat() throws Exception {
-// String requestBody = "{\"code\":\"test_code\"}";
-//
-// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andReturn();
-//
-// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
-//
-// if (responseBody.contains("\"code\":200")) {
-// String token = extractTokenFromResponse(responseBody);
-// if (token != null && !token.isEmpty()) {
-// Assertions.assertTrue(token.length() > 10, "Token 长度应大于10个字符");
-// System.out.println("Token 格式验证通过,Token: " + token);
-// } else {
-// System.out.println("未能提取到 Token");
-// }
-// } else {
-// System.out.println("登录失败,无法验证 Token 格式");
-// }
-// }
-//
-// @DisplayName("深i企登录 - 验证企业信息关联")
-// @Test
-// @Order(8)
-// public void testSiqLoginEnterpriseAssociation() throws Exception {
-// String requestBody = "{\"code\":\"test_code\"}";
-//
-// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
-// .contentType(MediaType.APPLICATION_JSON)
-// .content(requestBody))
-// .andDo(print())
-// .andExpect(status().isOk())
-// .andReturn();
-//
-// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
-//
-// if (responseBody.contains("\"code\":200")) {
-// String data = extractDataJson(responseBody);
-// if (data != null) {
-// String enterpriseId = extractJsonValue(data, "enterpriseId");
-// String enterpriseName = extractJsonValue(data, "enterpriseName");
-// String enterpriseNumber = extractJsonValue(data, "enterpriseNumber");
-//
-// if (enterpriseId != null && enterpriseName != null && enterpriseNumber != null) {
-// Assertions.assertFalse(enterpriseId.isEmpty(), "企业ID不应为空");
-// Assertions.assertFalse(enterpriseName.isEmpty(), "企业名称不应为空");
-// Assertions.assertFalse(enterpriseNumber.isEmpty(), "企业统一信用代码不应为空");
-// System.out.println("企业信息关联验证通过");
-// System.out.println("企业ID: " + enterpriseId);
-// System.out.println("企业名称: " + enterpriseName);
-// System.out.println("企业统一信用代码: " + enterpriseNumber);
-// }
-// }
-// } else {
-// System.out.println("登录失败,无法验证企业信息关联");
-// }
-// }
-//
-// // ==================== 工具方法 ====================
-//
-// /**
-// * 从 JSON 响应中提取 data 字段
-// */
-// private String extractDataJson(String responseBody) {
-// if (responseBody != null && responseBody.contains("\"data\":{")) {
-// int start = responseBody.indexOf("\"data\":{") + 7;
-// int end = responseBody.lastIndexOf("}");
-// if (start > 0 && end > start) {
-// return responseBody.substring(start, end + 1);
-// }
-// }
-// return null;
-// }
-//
-// /**
-// * 从响应中提取 Token
-// */
-// private String extractTokenFromResponse(String responseBody) {
-// return extractJsonValue(responseBody, "token");
-// }
-//
-// /**
-// * 从 JSON 字符串中提取指定字段的值
-// */
-// private String extractJsonValue(String json, String key) {
-// if (json != null && json.contains("\"" + key + "\"")) {
-// int start = json.indexOf("\"" + key + "\":\"") + key.length() + 4;
-// int end = json.indexOf("\"", start);
-// if (start > 0 && end > start) {
-// return json.substring(start, end);
-// }
-// }
-// return null;
-// }
-//}
-//{
-//}
diff --git a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/cp/AppEnfCpPlanControllerTest.java b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/cp/AppEnfCpPlanControllerTest.java
deleted file mode 100644
index f5978294..00000000
--- a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/rest/test/cp/AppEnfCpPlanControllerTest.java
+++ /dev/null
@@ -1,329 +0,0 @@
-package com.zdxt.rest.test.cp;
-
-import cn.dev33.satoken.context.mock.SaTokenContextMockUtil;
-import cn.dev33.satoken.stp.StpUtil;
-import cn.dev33.satoken.stp.parameter.SaLoginParameter;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.zdxt.enforcementcode.domain.bo.EnterpriseInformationBo;
-import com.zdxt.enforcementcode.domain.vo.EnterpriseInformationVo;
-import com.zdxt.enforcementcode.service.IEnterpriseInformationService;
-import org.dromara.ZdxtAdminApplication;
-import org.dromara.common.core.domain.model.LoginUser;
-import org.dromara.common.satoken.utils.LoginHelper;
-import org.junit.jupiter.api.*;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.http.MediaType;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.MvcResult;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import java.nio.charset.StandardCharsets;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
-
-/**
- * AppEnfCpPlanController 新增计划批量测试
- *
- * 为多个用户批量创建执法计划(每人100条)
- *
- */
-@SpringBootTest(classes = ZdxtAdminApplication.class)
-@AutoConfigureMockMvc
-@ActiveProfiles({"dev", "dev-cust-zrb"})
-@DisplayName("AppEnfCpPlanController 批量新增计划测试")
-@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
-public class AppEnfCpPlanControllerTest {
-
- @Autowired
- private MockMvc mockMvc;
-
- @Autowired
- private ObjectMapper objectMapper;
-
- @Autowired
- private IEnterpriseInformationService enterpriseInformationService;
-
- private static final String BASE_URL = "/app-enf/cpPlan";
- private static final String LOGIN_URL = "/app-enf/login/do";
- private static final String AES_KEY = "1234567898745621";
- private static final String CLIENT_ID = "f0535c2a32ab4d0496ab9a699b2a7d36";
- private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
-
- /** 通用密码 */
- private static final String PASSWORD = "szsf@zfjd";
-
- @BeforeEach
- public void setUp() {
- // 初始化 Sa-Token 上下文
- SaTokenContextMockUtil.setMockContext();
- MockHttpServletRequest mockRequest = new MockHttpServletRequest();
- mockRequest.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
- RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(mockRequest));
- }
-
- @AfterEach
- public void tearDown() {
- try {
- StpUtil.logout();
- } catch (Exception ignored) {
- }
- RequestContextHolder.resetRequestAttributes();
- SaTokenContextMockUtil.clearContext();
- }
-
- /**
- * 登录指定账号,返回登录信息
- */
- private Map doLogin(String account) throws Exception {
- String encryptedPassword = encryptByAes(PASSWORD);
- Map loginParams = new HashMap<>();
- loginParams.put("secretName", account);
- loginParams.put("secretKey", encryptedPassword);
-
- MvcResult loginResult = mockMvc.perform(post(LOGIN_URL)
- .header("User-Agent", USER_AGENT)
- .contentType(MediaType.APPLICATION_JSON)
- .content(objectMapper.writeValueAsString(loginParams)))
- .andExpect(status().isOk())
- .andExpect(jsonPath("$.code").value(200))
- .andReturn();
-
- String loginBody = loginResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
- JsonNode loginJson = objectMapper.readTree(loginBody);
- JsonNode data = loginJson.get("data");
-
- Map info = new HashMap<>();
- info.put("token", data.get("token").asText());
- info.put("userId", data.get("userId").asText());
- // nickName 可能为空,回退到 userName(中文姓名)
- String nickName = data.has("nickName") ? data.get("nickName").asText() : "";
- if (nickName == null || nickName.isBlank()) {
- nickName = data.has("userName") ? data.get("userName").asText() : account;
- }
- info.put("nickName", nickName);
- info.put("deptId", data.get("deptId").asText());
- info.put("deptName", data.get("deptName").asText());
- info.put("organId", data.get("organId").asText());
- info.put("organName", data.get("organName").asText());
- info.put("bureauUnitId", data.get("bureauUnitId").asText());
- info.put("bureauUnitName", data.get("bureauUnitName").asText());
- info.put("phonenumber", data.has("phonenumber") ? data.get("phonenumber").asText() : "");
-
- System.out.println("[" + account + "] 登录成功: userId=" + info.get("userId"));
- return info;
- }
-
- // ==================== 各账号批量新增测试 ====================
-
- @DisplayName("liuqianlin(刘倩琳)批量新增100条执法计划")
- @Test
- @Order(1)
- public void testBatchCreate_liuqianlin() throws Exception {
- batchCreatePlans("liuqianlin", 100);
- }
-
- @DisplayName("baining(白宁)批量新增100条执法计划")
- @Test
- @Order(2)
- public void testBatchCreate_baining() throws Exception {
- batchCreatePlans("baining", 100);
- }
-
- @DisplayName("caizifan(蔡梓帆)批量新增100条执法计划")
- @Test
- @Order(3)
- public void testBatchCreate_caizifan() throws Exception {
- batchCreatePlans("caizifan", 100);
- }
-
- @DisplayName("chenchong4(陈冲)批量新增100条执法计划")
- @Test
- @Order(4)
- public void testBatchCreate_chenchong4() throws Exception {
- batchCreatePlans("chenchong4", 100);
- }
-
- /**
- * 为指定账号批量新增计划
- *
- * 唯一性约束:同一人 + 日期 + 时间段 + 企业 只能有一条计划。
- * 日期循环31天(7月1~31日),时间段2个(上午/下午),企业循环7家,
- * 因 31、2、7 两两互素,由中国剩余定理(CRT)保证前 31×2×7=434 条组合均唯一,
- * 故 count≤434 时所有计划不会重复。
- *
- */
- private void batchCreatePlans(String account, int count) throws Exception {
- Map loginInfo = doLogin(account);
- String token = loginInfo.get("token");
- String userId = loginInfo.get("userId");
- String nickName = loginInfo.get("nickName");
-
- // 从数据库加载指定企业列表
- List enterprises = loadEnterprises();
- Assertions.assertFalse(enterprises.isEmpty(), "数据库中无可用企业数据");
-
- // --- 唯一性预测验证 ---
- int days = 31; // 7月有31天
- int timeSlots = 2; // 上午/下午
- int entCount = enterprises.size();
- // 由CRT保证的最大不重复组合数 = lcm(days, timeSlots, entCount) 当两两互素时 = days * timeSlots * entCount
- int maxUnique = days * timeSlots * entCount;
- int expectedSuccess = Math.min(count, maxUnique);
- System.out.println("[" + account + "] 企业数=" + entCount
- + ", 可用唯一组合(日期×时段×企业)=" + maxUnique
- + ", 计划生成数=" + count
- + ", 预计成功数=" + expectedSuccess);
- Assertions.assertTrue(count <= maxUnique,
- "计划数(" + count + ")超过最大唯一组合数(" + maxUnique + "),必然产生重复");
-
- Random random = new Random();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
- Calendar cal = Calendar.getInstance();
-
- int successCount = 0;
- int failCount = 0;
-
- for (int i = 0; i < count; i++) {
- // 所有计划日期限定在2026年7月内,循环使用7月1日~31日
- int dayOfMonth = (i % days) + 1;
- cal.set(2026, Calendar.JULY, dayOfMonth);
- String planDate = sdf.format(cal.getTime());
- long planTime = (i % 2 == 0) ? 1L : 2L; // 交替上午/下午
-
- // 确定性循环选取企业,保证 (日期, 时段, 企业) 三元组唯一
- EnterpriseInformationVo enterprise = enterprises.get(i % entCount);
- Map planBo = buildPlanBo(planDate, planTime, i, nickName, userId, loginInfo, enterprise, random);
- String requestBody = objectMapper.writeValueAsString(planBo);
-
- MvcResult result = mockMvc.perform(post(BASE_URL)
- .header("Authorization", "Bearer " + token)
- .header("clientid", CLIENT_ID)
- .header("User-Agent", USER_AGENT)
- .contentType(MediaType.APPLICATION_JSON)
- .content(requestBody))
- .andReturn();
-
- String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
- JsonNode respJson = objectMapper.readTree(responseBody);
- int code = respJson.get("code").asInt();
-
- if (code == 200) {
- successCount++;
- } else {
- failCount++;
- System.out.println("[" + account + "] 第" + (i + 1) + "条失败: " + responseBody);
- }
-
- if ((i + 1) % 10 == 0) {
- System.out.println("[" + account + "] 已处理 " + (i + 1) + "/" + count
- + ", 成功=" + successCount + ", 失败=" + failCount);
- }
- }
-
- System.out.println("========== [" + account + "] 批量新增完成 ==========");
- System.out.println("总计: " + count + ", 成功: " + successCount + ", 失败: " + failCount);
- Assertions.assertEquals(expectedSuccess, successCount,
- "[" + account + "] 预期成功" + expectedSuccess + "条,实际成功" + successCount + "条");
- }
-
- /** 指定的企业统一社会信用代码列表 */
- private static final String[][] ENTERPRISE_DATA = {
- {"吉田拉链(深圳)有限公司公明工厂", "91440300788302281W"},
- {"欧姆龙电子部件(深圳)有限公司", "914403007261811621"},
- {"深圳农牧美益肉业有限公司", "91440300662678582M"},
- {"深圳市深水龙岗污水处理有限公司", "914403006820066603"},
- {"深圳市强达电路股份有限公司", "91440300763461366N"},
- {"深圳康泰生物制品股份有限公司", "91440300618837873J"},
- {"深圳市里程食品有限公司", "91440300738848091F"},
- };
-
- /**
- * 从数据库加载指定的7家企业
- */
- private List loadEnterprises() {
- List result = new ArrayList<>();
- for (String[] entry : ENTERPRISE_DATA) {
- EnterpriseInformationBo queryBo = new EnterpriseInformationBo();
- queryBo.setEnterpriseNumber(entry[1]);
- queryBo.setIsDelete(0L);
- List list = enterpriseInformationService.queryList(queryBo);
- if (!list.isEmpty()) {
- result.add(list.get(0));
- } else {
- System.out.println("[警告] 未找到企业: " + entry[0] + " (" + entry[1] + ")");
- }
- }
- return result;
- }
-
- /**
- * 构建计划BO的Map
- */
- private Map buildPlanBo(String planDate, long planTime, int index,
- String userName, String userId, Map loginInfo,
- EnterpriseInformationVo enterprise, Random random) {
- Map bo = new LinkedHashMap<>();
- bo.put("planType", 1L); // 日常计划
- bo.put("planDate", planDate);
- bo.put("planTime", planTime);
- bo.put("enforceContent", "批量测试执法事项-第" + (index + 1) + "条");
- bo.put("enterpriseName", enterprise.getEnterpriseName());
- bo.put("enterpriseNumber", enterprise.getEnterpriseNumber());
- bo.put("enterpriseId", enterprise.getId());
- bo.put("enforceUserNames", userName);
- bo.put("enforceUserIds", userId);
- bo.put("enforceUserTels", loginInfo.get("phonenumber"));
- bo.put("enforceUserCodes", "-");
- bo.put("isPublic", random.nextInt(2) == 0 ? 0L : 1L); // 随机公开/不公开
- bo.put("isUnion", 1L); // 必须为联合执法,否则afterInsert会直接生成任务导致status变为3
- bo.put("reserveStatus", 1L); // 待预约
- bo.put("systemReserved", 0L);
- bo.put("manualReserved", 0L);
- bo.put("bureauDeptId", loginInfo.get("bureauUnitId"));
- bo.put("bureauDeptName", loginInfo.get("bureauUnitName"));
- bo.put("organId", loginInfo.get("organId"));
- bo.put("organName", loginInfo.get("organName"));
- bo.put("deptId", loginInfo.get("deptId"));
- bo.put("deptName", loginInfo.get("deptName"));
- bo.put("isDelete", 0L);
- return bo;
- }
-
- /**
- * AES/CBC/ZeroPadding 加密(与前端 CryptoJS 对应)
- */
- private String encryptByAes(String plainText) throws Exception {
- byte[] keyBytes = AES_KEY.getBytes(StandardCharsets.UTF_8);
- byte[] ivBytes = AES_KEY.getBytes(StandardCharsets.UTF_8);
-
- SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
- IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);
-
- // NoPadding 需要手动补零到16字节倍数
- byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
- int blockSize = 16;
- int paddedLen = ((plainBytes.length / blockSize) + 1) * blockSize;
- byte[] padded = new byte[paddedLen];
- System.arraycopy(plainBytes, 0, padded, 0, plainBytes.length);
- // 剩余字节默认为0(ZeroPadding)
-
- Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
- cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
- byte[] encrypted = cipher.doFinal(padded);
-
- return Base64.getEncoder().encodeToString(encrypted);
- }
-}
diff --git a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/ResetUserPasswordTest.java b/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/ResetUserPasswordTest.java
deleted file mode 100644
index d61a4e1c..00000000
--- a/zdxt-web-server/zdxt-admin-web-server/src/test/java/com/zdxt/service/test/ResetUserPasswordTest.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package com.zdxt.service.test;
-
-import cn.hutool.crypto.digest.DigestUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.zdxt.enforcementcode.domain.EnterpriseUser;
-import com.zdxt.enforcementcode.mapper.EnterpriseUserMapper;
-import org.dromara.ZdxtAdminApplication;
-import org.dromara.system.domain.SysUser;
-import org.dromara.system.mapper.SysUserMapper;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-
-import cn.dev33.satoken.context.mock.SaTokenContextMockUtil;
-import cn.dev33.satoken.stp.parameter.SaLoginParameter;
-import cn.dev33.satoken.stp.StpUtil;
-import org.dromara.common.core.domain.model.LoginUser;
-import org.dromara.common.satoken.utils.LoginHelper;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.test.context.ActiveProfiles;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
-
-/**
- * 批量重置 enterprise_user 表用户密码
- *
- * 密码加密规则: MD5(userName + password + salt)
- *
- */
-@SpringBootTest(classes = ZdxtAdminApplication.class)
-@AutoConfigureMockMvc
-@ActiveProfiles({"dev", "dev-cust-zrb"})
-@DisplayName("批量重置企业用户密码")
-public class ResetUserPasswordTest {
-
- @Autowired
- private EnterpriseUserMapper enterpriseUserMapper;
-
- @Autowired
- private SysUserMapper sysUserMapper;
-
- /** 重置后的明文密码 */
- private static final String NEW_PASSWORD = "szsf@zfjd";
- //private static final String NEW_PASSWORD = "Szsf@123";
-
- private static final String TEST_CLIENT_ID = "e5cd7e4891bf95d1d19206ce24a7b32e";
-
- @BeforeEach
- public void setUp() {
- // 初始化 Sa-Token 上下文(非 Web 环境下 StpUtil.login 需要)
- SaTokenContextMockUtil.setMockContext();
-
- // 设置模拟请求上下文(数据权限拦截器需要从 SaToken 上下文获取用户信息)
- MockHttpServletRequest mockRequest = new MockHttpServletRequest();
- mockRequest.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
- RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(mockRequest));
-
- // 构造测试用登录用户
- LoginUser loginUser = new LoginUser();
- loginUser.setUserId(1L);
- loginUser.setUserType("sys_user");
- loginUser.setTenantId("000000");
- loginUser.setUsername("test_admin");
- loginUser.setNickname("测试管理员");
- loginUser.setDeptId("103");
- loginUser.setDeptName("测试部门");
- loginUser.setRolePermission(new HashSet<>());
- loginUser.setMenuPermission(new HashSet<>());
-
- // 模拟登录
- SaLoginParameter param = new SaLoginParameter();
- param.setExtra(LoginHelper.CLIENT_KEY, TEST_CLIENT_ID);
- LoginHelper.login(loginUser, param);
- }
-
- @AfterEach
- public void tearDown() {
- try {
- StpUtil.logout();
- } catch (Exception ignored) {
- }
- RequestContextHolder.resetRequestAttributes();
- SaTokenContextMockUtil.clearContext();
- }
-
- @DisplayName("批量重置 enterprise_user 所有用户密码为 szsf@zfjd")
- @Test
- public void resetAllEnterpriseUserPassword() {
-
- /*-- 17608540150,weil45,"",15817307171,深圳农牧美益肉业有限公司,91440300662678582M,21
- -- 17608557492,DGD440881199506180622,"",15817381630,深圳市深水龙岗污水处理有限公司,914403006820066603,12
- -- 17608540121,smiledzb1982,"",13723454151,深圳康泰生物制品股份有限公司,91440300618837873J,10
- -- 17608594890,A7271888,"",13751661770,深圳市里程食品有限公司,91440300738848091F,9
- -- 17608565612,qintongzhen138,"",13823610579,欧姆龙电子部件(深圳)有限公司,914403007261811621,9
- -- 17608601734,XP073215,"",15012671807,深圳市强达电路股份有限公司,91440300763461366N,9
- -- 17608556724,33ef1970fd449676fa4bc197,"",13537602265,吉田拉链(深圳)有限公司公明工厂,91440300788302281W,8*/
-
- // 1. 指定需要重置密码的用户ID列表
- List userIds = Arrays.asList(
- // TODO: 在此填入需要重置的用户ID
- "17608540150", "17608557492", "17608540121", "17608594890", "17608565612", "17608601734", "17608556724","2064275054386966530","2064274295779979265","17608629742"
- );
-
- // 2. 根据ID列表查询企业用户
- List userList = enterpriseUserMapper.selectList(
- new LambdaQueryWrapper()
- .select(EnterpriseUser::getUserId, EnterpriseUser::getLoginName, EnterpriseUser::getUserName, EnterpriseUser::getSalt)
- .in(EnterpriseUser::getUserId, userIds)
- );
-
- System.out.println("查询到企业用户总数: " + userList.size());
-
- int successCount = 0;
- int skipCount = 0;
-
- for (EnterpriseUser user : userList) {
- String loginName = user.getLoginName();
- String salt = user.getSalt();
-
- if (loginName == null || loginName.isBlank()) {
- System.out.println("跳过: userId=" + user.getUserId() + ", loginName为空");
- skipCount++;
- continue;
- }
- if (salt == null || salt.isBlank()) {
- System.out.println("跳过: userId=" + user.getUserId() + ", salt为空");
- skipCount++;
- continue;
- }
-
- // 3. 按规则生成新密码: MD5(loginName + newPassword + salt)
- String newMd5Password = DigestUtil.md5Hex(loginName + NEW_PASSWORD + salt);
-
- // 4. 更新密码
- int rows = enterpriseUserMapper.update(null,
- new LambdaUpdateWrapper()
- .eq(EnterpriseUser::getUserId, user.getUserId())
- .set(EnterpriseUser::getPassword, newMd5Password)
- );
-
- if (rows > 0) {
- successCount++;
- }
- }
-
- System.out.println("========== 重置完成 ==========");
- System.out.println("成功: " + successCount + " 条");
- System.out.println("跳过: " + skipCount + " 条");
- System.out.println("新密码(明文): " + NEW_PASSWORD);
- }
-
-
- @DisplayName("批量重置 sys_user 指定用户密码为 szsf@zfjd")
- @Test
- public void resetSysUserPassword() {
- // 1. 执法端的测试用户
- List userIds = Arrays.asList(
- // TODO: 在此填入需要重置的用户ID
- 7897L, 17608416858L,17608416876L, 17608416904L,17608416912L, 17608416926L,17608416927L, 17608416945L,17608417058L,17608642193L,17608502852L,17608515249L,17608497168L
- );
-
- // 监督端的报表测试用户
-// userIds = Arrays.asList(
-// // TODO: 在此填入需要重置的用户ID
-// 17608417340L, 17608417451L,17608417716L, 17608614169L,17608614499L,7897L,17608634290L
-// );
-
- // 2. 根据ID列表查询系统用户
- List userList = sysUserMapper.selectList(
- new LambdaQueryWrapper()
- .select(SysUser::getUserId, SysUser::getLoginName, SysUser::getSalt)
- .in(SysUser::getUserId, userIds)
- );
-
- System.out.println("查询到系统用户总数: " + userList.size());
-
- int successCount = 0;
- int skipCount = 0;
-
- for (SysUser user : userList) {
- String loginName = user.getLoginName();
- String salt = user.getSalt();
-
- if (loginName == null || loginName.isBlank()) {
- System.out.println("跳过: userId=" + user.getUserId() + ", loginName为空");
- skipCount++;
- continue;
- }
- if (salt == null || salt.isBlank()) {
- System.out.println("跳过: userId=" + user.getUserId() + ", salt为空");
- skipCount++;
- continue;
- }
-
- // 3. 按规则生成新密码: MD5( + newPassword + salt)
- String newMd5Password = DigestUtil.md5Hex(loginName + NEW_PASSWORD + salt);
-
- // 4. 更新密码
- int rows = sysUserMapper.update(null,
- new LambdaUpdateWrapper()
- .eq(SysUser::getUserId, user.getUserId())
- .set(SysUser::getPassword, newMd5Password)
- );
-
- if (rows > 0) {
- successCount++;
- }
- }
-
- System.out.println("========== sys_user 重置完成 ==========");
- System.out.println("成功: " + successCount + " 条");
- System.out.println("跳过: " + skipCount + " 条");
- System.out.println("新密码(明文): " + NEW_PASSWORD);
- }
-
-}