Browse Source

增加2期临时登陆接入

v5
庄锐波 5 months ago
parent
commit
4aa3778b6a
  1. 8
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/CorsFilter.java
  2. 4
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/ShiroConfig.java
  3. 3
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/XssAndSqlHttpServletRequestWrapper.java
  4. 159
      lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/project/system/user/controller/LoginByUserIdController.java
  5. 8
      lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/jump.html
  6. 8
      lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/login.html

8
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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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-Credentials", "true");
httpresponse.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); 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("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN,token");
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"); httpresponse.addHeader("X-Frame-Options", "SAMEORIGIN");
}
// res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); // res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
// TODO 暂时允许options 判断请求方法是否为OPTIONS // TODO 暂时允许options 判断请求方法是否为OPTIONS
// if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { // if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {

4
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("/authLogin", "anon,captchaValidate");
filterChainDefinitionMap.put("/appLogin", "anon,captchaValidate"); filterChainDefinitionMap.put("/appLogin", "anon,captchaValidate");
filterChainDefinitionMap.put("/noPermission/login", "anon,captchaValidate"); filterChainDefinitionMap.put("/noPermission/login", "anon,captchaValidate");
filterChainDefinitionMap.put("/loginByUserId", "anon");
filterChainDefinitionMap.put("/small/**", "anon"); filterChainDefinitionMap.put("/small/**", "anon");
// 不拦截app登录 // 不拦截app登录
@ -306,6 +307,9 @@ public class ShiroConfig {
// 附件访问不拦截 // 附件访问不拦截
filterChainDefinitionMap.put("/profile/**", "anon"); filterChainDefinitionMap.put("/profile/**", "anon");
// 新闻发布接口不拦截(Vue前端跨域访问)
filterChainDefinitionMap.put("/code/demoInfoNew/**", "anon");
filterChainDefinitionMap.put("/safety/enterprise/register", "anon"); filterChainDefinitionMap.put("/safety/enterprise/register", "anon");
filterChainDefinitionMap.put("/safety/enterprise/registerSave", "anon"); filterChainDefinitionMap.put("/safety/enterprise/registerSave", "anon");

3
lib/EmergencyService/zdxtEmergencyAuthService/src/main/java/com/zdxt/auth/framework/config/XssAndSqlHttpServletRequestWrapper.java

@ -295,7 +295,8 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe
Map<String, String[]> submitParams = new HashMap(parameterMap); Map<String, String[]> submitParams = new HashMap(parameterMap);
Set<String> submitNames = submitParams.keySet(); Set<String> submitNames = submitParams.keySet();
for (String submitName : submitNames) { 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; return false;
} }
if ("cronExpression".equals(submitName)) { return false; } if ("cronExpression".equals(submitName)) { return false; }

159
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;
}
}
}

8
lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/jump.html

@ -21,7 +21,13 @@
<link href="../../static/css/style.default.css" th:href="@{/static/css/style.default.css}" rel="stylesheet"/> <link href="../../static/css/style.default.css" th:href="@{/static/css/style.default.css}" rel="stylesheet"/>
<script> <script>
if(window.top!==window.self){window.top.location=window.location}; (function(){
var now = new Date();
var start = new Date('2026-06-19');
var end = new Date('2026-08-01');
var inAllowedPeriod = (now >= start && now <= end);
if(!inAllowedPeriod && window.top!==window.self){window.top.location=window.location}
})();
</script> </script>
</head> </head>

8
lib/EmergencyService/zdxtEmergencyBootStart/src/main/resources/templates/login.html

@ -203,7 +203,13 @@
} }
</script> </script>
<script> <script>
if(window.top!==window.self){window.top.location=window.location} (function(){
var now = new Date();
var start = new Date('2026-06-19');
var end = new Date('2026-08-01');
var inAllowedPeriod = (now >= start && now <= end);
if(!inAllowedPeriod && window.top!==window.self){window.top.location=window.location}
})();
</script> </script>
</body> </body>
</html> </html>

Loading…
Cancel
Save