diff --git a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/CorsFilter.java b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/CorsFilter.java index a236e9e8..ef35d9c6 100644 --- a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/CorsFilter.java +++ b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/CorsFilter.java @@ -14,6 +14,7 @@ import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.time.LocalDate; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -61,7 +62,14 @@ public class CorsFilter implements Filter { httpresponse.addHeader("Access-Control-Allow-Credentials", "true"); httpresponse.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); httpresponse.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN,token"); - httpresponse.addHeader("X-Frame-Options", "SAMEORIGIN"); + LocalDate now = LocalDate.now(); + LocalDate start = LocalDate.of(2026, 6, 19); + LocalDate end = LocalDate.of(2026, 8, 1); + if (!now.isBefore(start) && !now.isAfter(end)) { + httpresponse.addHeader("Content-Security-Policy", "frame-ancestors 'self' http://localhost:85 http://localhost:12004 http://58.250.157.161 http://10.132.108.3:85 http://10.132.108.3"); + } else { + httpresponse.addHeader("X-Frame-Options", "SAMEORIGIN"); + } // res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); // TODO 暂时允许options 判断请求方法是否为OPTIONS // if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { diff --git a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/ShiroConfig.java b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/ShiroConfig.java index ca122384..5046ed52 100644 --- a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/ShiroConfig.java +++ b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/ShiroConfig.java @@ -284,6 +284,7 @@ public class ShiroConfig { filterChainDefinitionMap.put("/authLogin", "anon,captchaValidate"); filterChainDefinitionMap.put("/appLogin", "anon,captchaValidate"); filterChainDefinitionMap.put("/noPermission/login", "anon,captchaValidate"); + filterChainDefinitionMap.put("/loginByUserId", "anon"); filterChainDefinitionMap.put("/small/**", "anon"); // 不拦截app登录 @@ -306,6 +307,9 @@ public class ShiroConfig { // 附件访问不拦截 filterChainDefinitionMap.put("/profile/**", "anon"); + // 新闻发布接口不拦截(Vue前端跨域访问) + filterChainDefinitionMap.put("/code/demoInfoNew/**", "anon"); + filterChainDefinitionMap.put("/safety/enterprise/register", "anon"); filterChainDefinitionMap.put("/safety/enterprise/registerSave", "anon"); diff --git a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/XssAndSqlHttpServletRequestWrapper.java b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/XssAndSqlHttpServletRequestWrapper.java index db36fb7a..c67fa836 100644 --- a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/XssAndSqlHttpServletRequestWrapper.java +++ b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/XssAndSqlHttpServletRequestWrapper.java @@ -295,7 +295,8 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe Map submitParams = new HashMap(parameterMap); Set submitNames = submitParams.keySet(); for (String submitName : submitNames) { - if("secretName".equals(submitName) || "secretKey".equals(submitName) || "validateCode".equals(submitName)){ + if("secretName".equals(submitName) || "secretKey".equals(submitName) || "validateCode".equals(submitName) + || "v1_system_credential".equals(submitName)){ return false; } if ("cronExpression".equals(submitName)) { return false; } diff --git a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/project/system/user/controller/LoginByUserIdController.java b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/project/system/user/controller/LoginByUserIdController.java new file mode 100644 index 00000000..7351c4de --- /dev/null +++ b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/project/system/user/controller/LoginByUserIdController.java @@ -0,0 +1,159 @@ +package com.zdxt.auth.project.system.user.controller; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.zdxt.auth.framework.shiro.nopaddword.LoginType; +import com.zdxt.auth.framework.shiro.nopaddword.UserToken; +import com.zdxt.auth.framework.shiro.nopaddword.UserType; +import com.zdxt.auth.framework.web.controller.BaseController; +import com.zdxt.auth.project.system.user.service.IUserService; +import com.zdxt.domain.auth.User; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Base64; + +/** + * 通过用户ID登录 + */ +@Controller +public class LoginByUserIdController extends BaseController { + + private static final Logger log = LoggerFactory.getLogger(LoginByUserIdController.class); + + /** + * AES解密密钥(与新系统 EncryptUtils.encryptByAes 加密密钥一致) + */ + private static final String AES_KEY = "zdxt2026PlatForm"; + + /** + * 时间戳允许的最大偏移量(秒) + */ + private static final long ALLOWED_TIME_OFFSET_SECONDS = 20; + + /** + * 允许登录的开始日期时间(格式 yyyy-MM-dd HH:mm) + */ + private static final String ALLOWED_START_TIME = "2026-06-18 08:00"; + + /** + * 允许登录的结束日期时间(格式 yyyy-MM-dd HH:mm) + */ + private static final String ALLOWED_END_TIME = "2026-08-01 22:00"; + + @Autowired + private IUserService userService; + + /** + * 通过v1_system_credential免密登录,解密凭据后验证时间戳偏移并使用userId登录 + * + * @param v1SystemCredential AES加密的凭据(包含userid和ts) + * @return 跳转页面 + */ + @GetMapping("/loginByUserId") + public String loginByUserId(@RequestParam("v1_system_credential") String v1SystemCredential) { + // 0. 验证当前时间是否在允许的日期时间范围内 + if (!isWithinAllowedTime()) { + log.warn("通过userId登录失败, 当前时间不在允许的时间范围内[{} - {}]", + ALLOWED_START_TIME, ALLOWED_END_TIME); + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + + // 1. AES解密凭据 + String decryptedJson = decryptByAes(v1SystemCredential); + if (decryptedJson == null) { + log.warn("通过userId登录失败, v1_system_credential解密失败"); + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + + // 2. 解析JSON获取userid和ts + Long userId; + long ts; + try { + Gson gson = new Gson(); + JsonObject jsonObject = gson.fromJson(decryptedJson, JsonObject.class); + userId = Long.parseLong(jsonObject.get("userid").getAsString()); + ts = Long.parseLong(jsonObject.get("ts").getAsString()); + } catch (Exception e) { + log.warn("通过userId登录失败, 凭据JSON解析异常: {}", e.getMessage()); + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + + // 3. 验证时间戳是否与当前系统时间偏移在±20秒内 + long currentTimeMillis = System.currentTimeMillis(); + long diffSeconds = Math.abs(currentTimeMillis - ts) / 1000; + if (diffSeconds > ALLOWED_TIME_OFFSET_SECONDS) { + log.warn("通过userId登录失败, 时间戳偏移超过{}秒, ts: {}, 当前时间: {}, 偏移: {}秒", + ALLOWED_TIME_OFFSET_SECONDS, ts, currentTimeMillis, diffSeconds); + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + + // 4. 根据userId查询用户 + User sysUser = userService.selectUserById(userId); + if (sysUser == null) { + log.warn("通过userId登录失败, 用户不存在, userId: {}", userId); + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + + // 5. 使用免密登录方式进行Shiro认证 + UserToken token = new UserToken(sysUser.getLoginName(), LoginType.NOPASSWD, UserType.SYS.getType()); + Subject subject = SecurityUtils.getSubject(); + try { + subject.login(token); + log.info("通过v1_system_credential登录成功, userId: {}", userId); + return "redirect:/code/statisticalPanel/home-analysis"; + } catch (AuthenticationException e) { + log.error("通过userId登录认证失败, userId: {}, 原因: {}", userId, e.getMessage()); + throw new ResponseStatusException(HttpStatus.NOT_FOUND); + } + } + + /** + * 判断当前时间是否在允许的日期时间范围内 + * + * @return true-在允许时间范围内, false-不在允许时间范围内 + */ + private boolean isWithinAllowedTime() { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + LocalDateTime startTime = LocalDateTime.parse(ALLOWED_START_TIME, formatter); + LocalDateTime endTime = LocalDateTime.parse(ALLOWED_END_TIME, formatter); + LocalDateTime now = LocalDateTime.now(); + return !now.isBefore(startTime) && !now.isAfter(endTime); + } + + /** + * AES/ECB/PKCS5Padding 解密(对应新系统 EncryptUtils.encryptByAes 的加密方式) + * + * @param encryptedText Base64编码的AES密文 + * @return 解密后的明文字符串,解密失败返回null + */ + private String decryptByAes(String encryptedText) { + try { + byte[] keyBytes = AES_KEY.getBytes(StandardCharsets.UTF_8); + SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES"); + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, keySpec); + byte[] decodeBytes = Base64.getDecoder().decode(encryptedText); + byte[] decrypted = cipher.doFinal(decodeBytes); + return new String(decrypted, StandardCharsets.UTF_8); + } catch (Exception e) { + log.error("AES解密失败: {}", e.getMessage()); + return null; + } + } +} diff --git a/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/jump.html b/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/jump.html index b66729b4..0de78801 100644 --- a/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/jump.html +++ b/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/jump.html @@ -21,7 +21,13 @@ diff --git a/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/login.html b/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/login.html index 1f8ca386..6940f3f3 100644 --- a/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/login.html +++ b/lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/login.html @@ -203,7 +203,13 @@ }