From 9b023a659bf78d988b4cfbbae38a118081f2cb97 Mon Sep 17 00:00:00 2001 From: shil <452061493@qq.com> Date: Thu, 13 Aug 2026 09:53:17 +0800 Subject: [PATCH] =?UTF-8?q?fastjson=E5=8D=87=E7=BA=A7=20+=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/FastJson2JsonRedisSerializer.java | 18 ++- .../com/zdxt/common/util/FastJsonUtil.java | 106 ++++++++++++++++++ .../main/java/com/zdxt/domain/auth/Dept.java | 11 ++ .../controller/AppThirdLoginController.java | 35 ++++-- .../auth/framework/config/CorsFilter.java | 6 +- .../resources/mapper/system/DeptMapper.xml | 5 +- .../service/impl/ThirdLoginServiceImpl.java | 1 + .../main/java/com/zdxt/auth/dto/DeptBean.java | 11 ++ .../main/java/com/zdxt/auth/dto/UserBean.java | 15 ++- 9 files changed, 186 insertions(+), 22 deletions(-) create mode 100644 lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/util/FastJsonUtil.java diff --git a/lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/config/FastJson2JsonRedisSerializer.java b/lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/config/FastJson2JsonRedisSerializer.java index 89a32505..4986b87c 100644 --- a/lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/config/FastJson2JsonRedisSerializer.java +++ b/lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/config/FastJson2JsonRedisSerializer.java @@ -28,10 +28,14 @@ public class FastJson2JsonRedisSerializer implements RedisSerializer private Class clazz; /** - * 仅允许业务包 AutoType,避免全局打开 AutoTypeSupport。 - * 若 Redis 中还有其它包的 @type 对象,按需追加前缀。 + * 仅允许白名单包 AutoType,避免全局打开 AutoTypeSupport。 + * java.util/java.lang 用于兼容 WriteClassName 写出的集合等嵌套类型。 */ - private static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter("com.zdxt."); + private static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter( + "com.zdxt.", + "java.util.", + "java.lang." + ); public FastJson2JsonRedisSerializer(Class clazz) { @@ -46,7 +50,11 @@ public class FastJson2JsonRedisSerializer implements RedisSerializer { return new byte[0]; } - return JSON.toJSONBytes(t, JSONWriter.Feature.WriteClassName); + // FieldBased 避免 getter 副作用;ReferenceDetection 防止对象图循环导致序列化失败 + return JSON.toJSONBytes(t, + JSONWriter.Feature.WriteClassName, + JSONWriter.Feature.FieldBased, + JSONWriter.Feature.ReferenceDetection); } @Override @@ -56,7 +64,7 @@ public class FastJson2JsonRedisSerializer implements RedisSerializer { return null; } - return JSON.parseObject(bytes, clazz, AUTO_TYPE_FILTER); + return JSON.parseObject(bytes, clazz, AUTO_TYPE_FILTER, JSONReader.Feature.FieldBased); } public void setObjectMapper(ObjectMapper objectMapper) diff --git a/lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/util/FastJsonUtil.java b/lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/util/FastJsonUtil.java new file mode 100644 index 00000000..fc23bc0e --- /dev/null +++ b/lib/EmergencyBaseLib/EmergencyCommon/src/main/java/com/zdxt/common/util/FastJsonUtil.java @@ -0,0 +1,106 @@ +package com.zdxt.common.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; + +/** + * Fastjson2 解析工具。 + *

+ * 兼容包对 String 走 JSONReaderUTF16,在部分 JDK(尤其 Oracle/麒麟 aarch64)上会误报 + * {@code invalid escape character EOI}。统一走 UTF-8 字节解析规避该问题,失败时再用 Jackson 兜底。 + */ +public final class FastJsonUtil { + + private static final ObjectMapper JACKSON = new ObjectMapper(); + + private FastJsonUtil() { + } + + public static JSONObject parseObject(String text) { + if (text == null) { + return null; + } + String trimmed = text.trim(); + if (trimmed.isEmpty() || "null".equalsIgnoreCase(trimmed)) { + return null; + } + try { + // 关键 UTF-8 字节路径,避开 JSONReaderUTF16 的 EOI 误判 + return JSON.parseObject(trimmed.getBytes(StandardCharsets.UTF_8)); + } catch (Exception fastjsonEx) { + try { + @SuppressWarnings("unchecked") + Map map = JACKSON.readValue(trimmed, Map.class); + return new JSONObject(map); + } catch (Exception jacksonEx) { + fastjsonEx.addSuppressed(jacksonEx); + if (fastjsonEx instanceof RuntimeException) { + throw (RuntimeException) fastjsonEx; + } + throw new RuntimeException(fastjsonEx); + } + } + } + + public static JSONArray parseArray(String text) { + if (text == null) { + return null; + } + String trimmed = text.trim(); + if (trimmed.isEmpty() || "null".equalsIgnoreCase(trimmed)) { + return null; + } + try { + Object parsed = JSON.parse(trimmed.getBytes(StandardCharsets.UTF_8)); + if (parsed instanceof JSONArray) { + return (JSONArray) parsed; + } + if (parsed == null) { + return null; + } + JSONArray arr = new JSONArray(); + arr.add(parsed); + return arr; + } catch (Exception fastjsonEx) { + try { + List list = JACKSON.readValue(trimmed, List.class); + return new JSONArray(list); + } catch (Exception jacksonEx) { + fastjsonEx.addSuppressed(jacksonEx); + if (fastjsonEx instanceof RuntimeException) { + throw (RuntimeException) fastjsonEx; + } + throw new RuntimeException(fastjsonEx); + } + } + } + + public static T parseObject(String text, Class clazz) { + if (text == null) { + return null; + } + String trimmed = text.trim(); + if (trimmed.isEmpty() || "null".equalsIgnoreCase(trimmed)) { + return null; + } + try { + return JSON.parseObject(trimmed.getBytes(StandardCharsets.UTF_8), clazz); + } catch (Exception fastjsonEx) { + try { + return JACKSON.readValue(trimmed, clazz); + } catch (Exception jacksonEx) { + fastjsonEx.addSuppressed(jacksonEx); + if (fastjsonEx instanceof RuntimeException) { + throw (RuntimeException) fastjsonEx; + } + throw new RuntimeException(fastjsonEx); + } + } + } +} diff --git a/lib/EmergencyBaseLib/EmergencyCommonEntity/src/main/java/com/zdxt/domain/auth/Dept.java b/lib/EmergencyBaseLib/EmergencyCommonEntity/src/main/java/com/zdxt/domain/auth/Dept.java index 11764653..64fca431 100644 --- a/lib/EmergencyBaseLib/EmergencyCommonEntity/src/main/java/com/zdxt/domain/auth/Dept.java +++ b/lib/EmergencyBaseLib/EmergencyCommonEntity/src/main/java/com/zdxt/domain/auth/Dept.java @@ -216,6 +216,17 @@ public class Dept extends BaseDomain { */ private String unitLevel; + /** 所属区 */ + private String areaNode; + + public String getAreaNode() { + return areaNode; + } + + public void setAreaNode(String areaNode) { + this.areaNode = areaNode; + } + public String getDwxz() { return dwxz; } diff --git a/lib/EmergencyService/zdxtEmergencyAppService/src/main/java/com/zdxt/app/controller/AppThirdLoginController.java b/lib/EmergencyService/zdxtEmergencyAppService/src/main/java/com/zdxt/app/controller/AppThirdLoginController.java index d13f74fe..21d72941 100644 --- a/lib/EmergencyService/zdxtEmergencyAppService/src/main/java/com/zdxt/app/controller/AppThirdLoginController.java +++ b/lib/EmergencyService/zdxtEmergencyAppService/src/main/java/com/zdxt/app/controller/AppThirdLoginController.java @@ -20,6 +20,7 @@ import com.zdxt.code.utils.ServiceInvocation; import com.zdxt.common.util.IdCardCryptoUtil; import com.zdxt.code.utils.ZwSmsClient; import com.zdxt.common.ZDResponse; +import com.zdxt.common.util.FastJsonUtil; import com.zdxt.common.util.JedisUtil; import com.zdxt.common.util.RedisCache; import com.zdxt.common.util.StringUtils; @@ -145,18 +146,37 @@ public class AppThirdLoginController { try { // 获取 access_token accessTokenJson = HttpUtil.HttpSendGet(szyptUrl + "/cgi-bin/gettoken?corpid="+szyptCorpid+"&corpsecret="+szyptCorpsecret, null); - JSONObject tokenObj = JSONObject.parseObject(accessTokenJson); + JSONObject tokenObj = FastJsonUtil.parseObject(accessTokenJson); String token = tokenObj.getString("access_token"); // 获取 用户Id userJson = HttpUtil.HttpSendGet(szyptUrl + "/cgi-bin/user/getuserinfo?access_token="+token+"&code="+code, null); log.info(">>> {} 市认证用户信息: {}", code, userJson); - JSONObject userOjb = JSONObject.parseObject(userJson); + if (StringUtils.isEmpty(userJson)) { + throw new RuntimeException("市认证 getuserinfo 返回为空"); + } + // fastjson2 兼容包对空串会返回 null,需先判空再取值,避免 NPE 被误判为解析失败 + JSONObject userOjb = FastJsonUtil.parseObject(userJson); + if (userOjb == null) { + throw new RuntimeException("市认证用户信息解析失败: " + userJson); + } + // 旧接口字段 UserId,新接口多为 userid,兼容两种 String userId = userOjb.getString("UserId"); + if (StringUtils.isEmpty(userId)) { + userId = userOjb.getString("userid"); + } + if (StringUtils.isEmpty(userId)) { + throw new RuntimeException("市认证未返回 UserId/userid, errcode=" + + userOjb.getString("errcode") + ", errmsg=" + userOjb.getString("errmsg") + + ", body=" + userJson); + } // UserBean userBean = userApi.getUserByUserStrId(userId); // user = iUserService.selectUserByLoginName(userId); List us = iUserService.selectUserByLoginNameD(userId); user = null!=us && us.size()>0 ? us.get(0) : null; + if (user == null) { + throw new RuntimeException("本系统未找到对应用户, loginName=" + userId); + } // todo:这里需要将转换出来的User存redis用于做权限 redisCache.setCacheObject("shiro:app:"+user.getUserId(), user); @@ -169,8 +189,7 @@ public class AppThirdLoginController { // return thirdLoginService.szyLogin2(user); log.error("---> {} 市认证用户信息: {}", code, userJson); log.error("---> 本系统用户信息: {}", user); - log.error(e.getMessage()); - e.printStackTrace(); + log.error("---> 深政易登录异常", e); } return ZDResponse.success(); @@ -188,10 +207,10 @@ public class AppThirdLoginController { log.info("获取政务微信认证签名URL:{}",url); // 获取 access_token String accessTokenJson = HttpUtil.HttpSendGet(szyptUrl + "/cgi-bin/gettoken?corpid="+szyptCorpid+"&corpsecret="+szyptCorpsecret, null); - JSONObject tokenObj = JSONObject.parseObject(accessTokenJson); + JSONObject tokenObj = FastJsonUtil.parseObject(accessTokenJson); String token = tokenObj.getString("access_token"); String jsapiTicket = HttpUtil.HttpSendGet(szyptUrl + "/cgi-bin/get_jsapi_ticket?access_token="+token, null); - JSONObject ticketObj = JSONObject.parseObject(jsapiTicket); + JSONObject ticketObj = FastJsonUtil.parseObject(jsapiTicket); String ticket = ticketObj.getString("ticket"); log.info("====================== jsapiTicket start ======================"); log.info("ticket: {}",ticket); @@ -281,7 +300,7 @@ public class AppThirdLoginController { } log.info("---> data: {}", data); - JSONObject jsonObject = JSONObject.parseObject(data); + JSONObject jsonObject = FastJsonUtil.parseObject(data); JSONObject userInfo = (JSONObject) jsonObject.get("data"); log.info("---> userInfo: {}", userInfo.toJSONString()); @@ -340,7 +359,7 @@ public class AppThirdLoginController { params.put("appCode",code); String data = HttpUtil.httpSendPost(siqUrl+ "/pub/auth/getUserInfo", JSONObject.toJSONString(params),new HashMap<>()); - JSONObject jsonObject = JSONObject.parseObject(data); + JSONObject jsonObject = FastJsonUtil.parseObject(data); JSONObject userInfo = (JSONObject) jsonObject.get("data"); log.info("================= userInfo ================="); 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 ef35d9c6..8938a622 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 @@ -34,7 +34,7 @@ public class CorsFilter implements Filter { //配置可信域名 String[] authhosts = {"http://10.132.108.3:85","http://jdm.szssfj.cn","http://localhost:85","http://192.168.31.196:3301","http://172.16.20.74:85", "http://192.168.145.155", "http://zfjdm.lggov.cn", "https://zfjdm.lggov.cn", "http://localhost:3301","http://10.132.108.3:81","http://10.132.108.3:85", "http://192.168.1.130:3301", "http://172.16.20.74:3301", "http://10.132.108.1", "http://10.132.108.6", - "http://192.168.129.149","http://192.168.129.150","http://192.168.129.151","http://192.168.129.512","http://192.168.129.513","http://192.168.129.154","http://192.168.129.157","http://192.168.129.158"}; + "http://192.168.129.149","http://192.168.129.150","http://192.168.129.151","http://192.168.129.512","http://192.168.129.513","http://192.168.129.154","http://192.168.129.157","http://192.168.129.158", "http://10.132.108.18","http://10.132.108.18:12004"}; String authost = ""; HttpServletRequest httprequest = (HttpServletRequest) request; String origin = httprequest.getHeader("Origin"); @@ -64,9 +64,9 @@ public class CorsFilter implements Filter { 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); + LocalDate end = LocalDate.of(2026, 10, 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"); + 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 http://10.132.108.18 http://10.132.108.18:12004"); } else { httpresponse.addHeader("X-Frame-Options", "SAMEORIGIN"); } diff --git a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/resources/mapper/system/DeptMapper.xml b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/resources/mapper/system/DeptMapper.xml index 40996899..64d01a8c 100644 --- a/lib/EmergencyService/zdxtEmergencyAuthService/src/main/resources/mapper/system/DeptMapper.xml +++ b/lib/EmergencyService/zdxtEmergencyAuthService/src/main/resources/mapper/system/DeptMapper.xml @@ -64,6 +64,7 @@ + @@ -255,8 +256,8 @@ diff --git a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/ThirdLoginServiceImpl.java b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/ThirdLoginServiceImpl.java index 9c1e1dde..78e70e13 100644 --- a/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/ThirdLoginServiceImpl.java +++ b/lib/EmergencyService/zdxtLawEnforcementCodeService/src/main/java/com/zdxt/code/service/impl/ThirdLoginServiceImpl.java @@ -217,6 +217,7 @@ public class ThirdLoginServiceImpl implements ThirdLoginService { payload.put("name", user.getLoginName()); String token1 = JWTUtils.sign(payload); user.setToken(token1); + user.setArea(dept.getAreaNode()); return ZDResponse.success("登录成功",user); } catch (Exception e) { log.error(e.getMessage()); diff --git a/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/DeptBean.java b/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/DeptBean.java index fa9679ba..db3abaab 100644 --- a/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/DeptBean.java +++ b/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/DeptBean.java @@ -130,6 +130,17 @@ public class DeptBean extends BaseDomain { private String zzDisplayPath; + /** 所属区 */ + private String areaNode; + + public String getAreaNode() { + return areaNode; + } + + public void setAreaNode(String areaNode) { + this.areaNode = areaNode; + } + public String getZzDisplayPath() { return zzDisplayPath; } diff --git a/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/UserBean.java b/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/UserBean.java index 26c144e8..734bda97 100644 --- a/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/UserBean.java +++ b/lib/EmergencyServiceApi/emergencyAuthServiceApi/src/main/java/com/zdxt/auth/dto/UserBean.java @@ -127,10 +127,6 @@ public class UserBean implements Serializable { private String password; - - - - /** 部门id */ private String organizationId; /** 用户ID */ @@ -193,6 +189,17 @@ public class UserBean implements Serializable { */ private String kingdeeUserId; + /** 所属区 */ + private String area; + + public String getArea() { + return area; + } + + public void setArea(String area) { + this.area = area; + } + public String getKingdeeOrgId() { return kingdeeOrgId; }