From 8b211fbad6e31ab12787b78a71d1fa85d884d320 Mon Sep 17 00:00:00 2001
From: wangys <3401275564@qq.com>
Date: Thu, 11 Dec 2025 18:30:35 +0800
Subject: [PATCH] gateway
---
.../database/postgres/sql/createTableUser.sql | 3 +
urbanLifelineServ/.vscode/launch.json | 95 +++++++--
.../agent/src/main/resources/application.yml | 4 +-
urbanLifelineServ/apis/api-system/pom.xml | 12 ++
.../org/xyzh/api/system/vo/SysUserVO.java | 15 +-
.../src/main/java/org/xyzh/auth/AuthApp.java | 2 +
.../auth/service/impl/AuthServiceImpl.java | 7 +-
.../strategy/impl/PasswordLoginStrategy.java | 2 +
.../strategy/impl/PhoneLoginStrategy.java | 5 +-
.../auth/src/main/resources/application.yml | 18 +-
.../src/main/resources/application.yml | 4 +-
urbanLifelineServ/common/common-dto/pom.xml | 5 +
.../org/xyzh/common/dto/sys/TbSysUserDTO.java | 12 +-
urbanLifelineServ/common/common-utils/pom.xml | 5 +-
.../common/utils/crypto/AesEncryptUtil.java | 70 ++++++-
.../utils/crypto/TypeHandlerConfig.java | 37 ++++
.../src/main/resources/application.yml | 4 +-
.../file/src/main/resources/application.yml | 4 +-
urbanLifelineServ/gateway/pom.xml | 11 -
.../org/xyzh/gateway/GatewayApplication.java | 10 +-
.../gateway/config/GatewaySecurityConfig.java | 32 +++
.../GatewayDiagnosticController.java | 59 ++++++
.../src/main/resources/application-dev.yml | 16 +-
.../src/main/resources/application.yml | 197 ++++++++++--------
.../log/src/main/resources/application.yml | 4 +-
.../src/main/resources/application.yml | 4 +-
.../src/main/resources/application.yml | 4 +-
.../service/impl/SysUserServiceImpl.java | 9 +-
.../src/main/resources/application-dev.yml | 7 +
.../system/src/main/resources/application.yml | 4 +-
.../mapper/user/TbSysUserInfoMapper.xml | 73 ++-----
.../resources/mapper/user/TbSysUserMapper.xml | 57 ++---
.../mapper/user/TbSysUserRoleMapper.xml | 30 ++-
.../src/main/resources/application.yml | 4 +-
.../platform/localSharedImportMap.js | 4 +-
35 files changed, 527 insertions(+), 302 deletions(-)
create mode 100644 urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/TypeHandlerConfig.java
create mode 100644 urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/config/GatewaySecurityConfig.java
create mode 100644 urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/controller/GatewayDiagnosticController.java
diff --git a/urbanLifelineServ/.bin/database/postgres/sql/createTableUser.sql b/urbanLifelineServ/.bin/database/postgres/sql/createTableUser.sql
index 41d04f22..22e0f225 100644
--- a/urbanLifelineServ/.bin/database/postgres/sql/createTableUser.sql
+++ b/urbanLifelineServ/.bin/database/postgres/sql/createTableUser.sql
@@ -13,11 +13,13 @@ CREATE TABLE sys.tb_sys_user (
phone VARCHAR(500), -- 电话号码
phone_hash VARCHAR(200), -- 电话hash
wechat_id VARCHAR(50), -- 微信ID
+ creator VARCHAR(50) DEFAULT NULL, -- 创建者
create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间(使用带时区时间)
update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(由触发器维护)
delete_time TIMESTAMPTZ DEFAULT NULL, -- 删除时间
deleted BOOLEAN NOT NULL DEFAULT false, -- 是否删除(使用 BOOLEAN)
status INTEGER NOT NULL DEFAULT 1, -- 状态
+ remark VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (user_id),
UNIQUE (optsn),
UNIQUE (email),
@@ -59,6 +61,7 @@ CREATE TABLE sys.tb_sys_user_info (
level INTEGER DEFAULT 1, -- 等级
id_card VARCHAR(50), -- 身份证号
address VARCHAR(255), -- 地址
+ creator VARCHAR(50) DEFAULT NULL, -- 创建者
remark VARCHAR(500) DEFAULT NULL, -- 备注
create_time TIMESTAMPTZ NOT NULL DEFAULT now(), -- 创建时间
update_time TIMESTAMPTZ DEFAULT NULL, -- 更新时间(触发器维护)
diff --git a/urbanLifelineServ/.vscode/launch.json b/urbanLifelineServ/.vscode/launch.json
index 756c8bcb..665994fe 100644
--- a/urbanLifelineServ/.vscode/launch.json
+++ b/urbanLifelineServ/.vscode/launch.json
@@ -1,6 +1,13 @@
{
"version": "0.2.0",
"configurations": [
+ {
+ "type": "java",
+ "name": "AesEncryptUtil",
+ "request": "launch",
+ "mainClass": "org.xyzh.common.utils.crypto.AesEncryptUtil",
+ "projectName": "common-utils"
+ },
{
"type": "java",
"name": "Gateway (8180)",
@@ -8,8 +15,12 @@
"mainClass": "org.xyzh.gateway.GatewayApplication",
"projectName": "gateway",
"cwd": "${workspaceFolder}/gateway",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8180"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8180"
+ ],
"console": "integratedTerminal"
},
{
@@ -19,8 +30,12 @@
"mainClass": "org.xyzh.auth.AuthApp",
"projectName": "auth",
"cwd": "${workspaceFolder}/auth",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8181"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8181"
+ ],
"console": "integratedTerminal"
},
{
@@ -30,8 +45,12 @@
"mainClass": "org.xyzh.system.SystemApp",
"projectName": "system",
"cwd": "${workspaceFolder}/system",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8182"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8182"
+ ],
"console": "integratedTerminal"
},
{
@@ -41,8 +60,12 @@
"mainClass": "org.xyzh.log.LogApp",
"projectName": "log",
"cwd": "${workspaceFolder}/log",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8183"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8183"
+ ],
"console": "integratedTerminal"
},
{
@@ -52,8 +75,12 @@
"mainClass": "org.xyzh.file.FileApp",
"projectName": "file",
"cwd": "${workspaceFolder}/file",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8184"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8184"
+ ],
"console": "integratedTerminal"
},
{
@@ -63,8 +90,12 @@
"mainClass": "org.xyzh.message.MessageApp",
"projectName": "message",
"cwd": "${workspaceFolder}/message",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8185"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8185"
+ ],
"console": "integratedTerminal"
},
{
@@ -74,8 +105,12 @@
"mainClass": "org.xyzh.bidding.BiddingApp",
"projectName": "bidding",
"cwd": "${workspaceFolder}/bidding",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8186"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8186"
+ ],
"console": "integratedTerminal"
},
{
@@ -85,8 +120,12 @@
"mainClass": "org.xyzh.platform.PlatformApp",
"projectName": "platform",
"cwd": "${workspaceFolder}/platform",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8187"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8187"
+ ],
"console": "integratedTerminal"
},
{
@@ -96,8 +135,12 @@
"mainClass": "org.xyzh.workcase.WorkcaseApp",
"projectName": "workcase",
"cwd": "${workspaceFolder}/workcase",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8188"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8188"
+ ],
"console": "integratedTerminal"
},
{
@@ -107,8 +150,12 @@
"mainClass": "org.xyzh.crontab.CrontabApp",
"projectName": "crontab",
"cwd": "${workspaceFolder}/crontab",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8189"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8189"
+ ],
"console": "integratedTerminal"
},
{
@@ -118,8 +165,12 @@
"mainClass": "org.xyzh.agent.AgentApp",
"projectName": "agent",
"cwd": "${workspaceFolder}/agent",
- "args": ["--spring.profiles.active=dev"],
- "vmArgs": ["-Dserver.port=8190"],
+ "args": [
+ "--spring.profiles.active=dev"
+ ],
+ "vmArgs": [
+ "-Dserver.port=8190"
+ ],
"console": "integratedTerminal"
}
],
diff --git a/urbanLifelineServ/agent/src/main/resources/application.yml b/urbanLifelineServ/agent/src/main/resources/application.yml
index 34d3bfee..8de48c16 100644
--- a/urbanLifelineServ/agent/src/main/resources/application.yml
+++ b/urbanLifelineServ/agent/src/main/resources/application.yml
@@ -1,8 +1,8 @@
# ================== Server ==================
server:
port: 8190
- servlet:
- context-path: /urban-lifeline/agent
+ # servlet:
+ # context-path: /urban-lifeline/agent # 微服务架构下,context-path由Gateway管理
# ================== Auth ====================
urban-lifeline:
diff --git a/urbanLifelineServ/apis/api-system/pom.xml b/urbanLifelineServ/apis/api-system/pom.xml
index 1e68a181..3f6de234 100644
--- a/urbanLifelineServ/apis/api-system/pom.xml
+++ b/urbanLifelineServ/apis/api-system/pom.xml
@@ -18,5 +18,17 @@
21
21
+
+
+ org.xyzh.common
+ common-dto
+ ${urban-lifeline.version}
+
+
+ org.xyzh.common
+ common-utils
+ ${urban-lifeline.version}
+
+
\ No newline at end of file
diff --git a/urbanLifelineServ/apis/api-system/src/main/java/org/xyzh/api/system/vo/SysUserVO.java b/urbanLifelineServ/apis/api-system/src/main/java/org/xyzh/api/system/vo/SysUserVO.java
index fdcd944b..700e8903 100644
--- a/urbanLifelineServ/apis/api-system/src/main/java/org/xyzh/api/system/vo/SysUserVO.java
+++ b/urbanLifelineServ/apis/api-system/src/main/java/org/xyzh/api/system/vo/SysUserVO.java
@@ -7,6 +7,7 @@ import org.xyzh.common.vo.BaseVO;
import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.common.dto.sys.TbSysUserInfoDTO;
+import org.xyzh.common.utils.crypto.AesEncryptUtil;
import java.util.List;
@@ -34,7 +35,7 @@ public class SysUserVO extends BaseVO {
@Schema(description = "邮箱")
private String email;
-
+
@Schema(description = "手机")
private String phone;
@@ -47,8 +48,8 @@ public class SysUserVO extends BaseVO {
@Schema(description = "用户状态")
private String status;
- @Schema(description = "用户类型")
- private String userType;
+ @Schema(description = "创建人")
+ private String creator;
// TbSysUserInfoDTO对应字段
@Schema(description = "用户名")
@@ -79,6 +80,11 @@ public class SysUserVO extends BaseVO {
@Schema(description = "用户视图权限列表")
private List viewPermissions;
+ public void setPhone(String phone){
+ this.phone = phone;
+ this.phoneHash = AesEncryptUtil.maskPhone(phone);
+ }
+
public static TbSysUserDTO toDTO(SysUserVO vo) {
if (vo == null) {
return null;
@@ -91,10 +97,8 @@ public class SysUserVO extends BaseVO {
dto.setPhone(vo.getPhone());
dto.setWechatId(vo.getWechatId());
dto.setStatus(vo.getStatus());
- dto.setUserType(vo.getUserType());
dto.setOptsn(vo.getOptsn());
dto.setCreator(vo.getCreator());
- dto.setUpdater(vo.getUpdater());
dto.setDeptPath(vo.getDeptPath());
dto.setRemark(vo.getRemark());
dto.setCreateTime(vo.getCreateTime());
@@ -120,7 +124,6 @@ public class SysUserVO extends BaseVO {
// 继承自 BaseDTO 的字段
userInfoDTO.setOptsn(userVO.getOptsn());
userInfoDTO.setCreator(userVO.getCreator());
- userInfoDTO.setUpdater(userVO.getUpdater());
userInfoDTO.setDeptPath(userVO.getDeptPath());
userInfoDTO.setRemark(userVO.getRemark());
userInfoDTO.setCreateTime(userVO.getCreateTime());
diff --git a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/AuthApp.java b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/AuthApp.java
index 6f512620..5d9d2b93 100644
--- a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/AuthApp.java
+++ b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/AuthApp.java
@@ -5,10 +5,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@EnableDubbo // 启用 Dubbo 服务
+@EnableDiscoveryClient // 启用 Nacos 服务注册与发现(用于 Gateway 路由)
@ComponentScan(basePackages = {
"org.xyzh.auth", // 当前auth模块
"org.xyzh.common" // 公共模块
diff --git a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/service/impl/AuthServiceImpl.java b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/service/impl/AuthServiceImpl.java
index c6d969f5..ac1981c8 100644
--- a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/service/impl/AuthServiceImpl.java
+++ b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/service/impl/AuthServiceImpl.java
@@ -24,6 +24,7 @@ import org.xyzh.common.dto.sys.TbSysPermissionDTO;
import org.xyzh.common.dto.sys.TbSysViewDTO;
import org.xyzh.common.redis.service.RedisService;
import org.xyzh.common.utils.IDUtils;
+import org.xyzh.common.utils.crypto.AesEncryptUtil;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
@@ -67,6 +68,9 @@ public class AuthServiceImpl implements AuthService{
@Autowired
private LoginStrategyFactory loginStrategyFactory;
+ @Autowired
+ private AesEncryptUtil aesEncryptUtil;
+
@Override
public ResultDomain getCaptcha(LoginParam loginParam) {
try {
@@ -236,7 +240,8 @@ public class AuthServiceImpl implements AuthService{
// 5. 验证凭据
if ("password".equals(loginType)) {
- if (!strategy.verifyCredential(loginParam.getPassword(), user.getPassword())) {
+ String pwd = aesEncryptUtil.decrypt(loginParam.getPassword());
+ if (!strategy.verifyCredential(pwd, user.getPassword())) {
logLoginAttempt(loginParam, user, false, loginAttempt, "密码错误");
return ResultDomain.failure("密码错误");
}
diff --git a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PasswordLoginStrategy.java b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PasswordLoginStrategy.java
index 8a2588a3..75dab48c 100644
--- a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PasswordLoginStrategy.java
+++ b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PasswordLoginStrategy.java
@@ -7,6 +7,7 @@ import org.xyzh.auth.strategy.LoginStrategy;
import org.xyzh.common.core.domain.LoginParam;
import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.common.utils.NonUtils;
+import org.xyzh.common.utils.crypto.AesEncryptUtil;
import org.xyzh.common.utils.validation.method.EmailValidateMethod;
import org.xyzh.common.utils.validation.method.PhoneValidateMethod;
import org.xyzh.api.system.service.SysUserService;
@@ -77,6 +78,7 @@ public class PasswordLoginStrategy implements LoginStrategy {
@Override
public boolean verifyCredential(String inputCredential, String storedCredential) {
// 使用BCrypt的matches方法验证密码(内部会自动处理salt)
+ logger.info(passwordEncoder.encode(inputCredential));
return passwordEncoder.matches(inputCredential, storedCredential);
}
}
\ No newline at end of file
diff --git a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PhoneLoginStrategy.java b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PhoneLoginStrategy.java
index bd48fbd3..58a7a3ee 100644
--- a/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PhoneLoginStrategy.java
+++ b/urbanLifelineServ/auth/src/main/java/org/xyzh/auth/strategy/impl/PhoneLoginStrategy.java
@@ -5,10 +5,11 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.xyzh.auth.strategy.LoginStrategy;
import org.xyzh.common.core.domain.LoginParam;
-import org.xyzh.common.dto.sys.TbSysUserDTO;
import org.xyzh.api.system.service.SysUserService;
import org.xyzh.api.system.vo.SysUserVO;
import org.xyzh.common.redis.service.RedisService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* @description PhoneLoginStrategy.java文件描述 手机号登录策略
@@ -19,6 +20,7 @@ import org.xyzh.common.redis.service.RedisService;
*/
@Component
public class PhoneLoginStrategy implements LoginStrategy {
+ private static final Logger logger = LoggerFactory.getLogger(PhoneLoginStrategy.class);
@Autowired
private SysUserService userService;
@@ -57,7 +59,6 @@ public class PhoneLoginStrategy implements LoginStrategy {
@Override
public boolean verifyCredential(String inputCredential, String storedCredential) {
- // 密码验证
return passwordEncoder.matches(inputCredential, storedCredential);
}
diff --git a/urbanLifelineServ/auth/src/main/resources/application.yml b/urbanLifelineServ/auth/src/main/resources/application.yml
index 4c3c285f..d10418be 100644
--- a/urbanLifelineServ/auth/src/main/resources/application.yml
+++ b/urbanLifelineServ/auth/src/main/resources/application.yml
@@ -1,18 +1,20 @@
# ================== Server ==================
server:
port: 8181
- servlet:
- context-path: /urban-lifeline/auth
+ # servlet:
+ # context-path: /urban-lifeline/auth # 微服务架构下,context-path由Gateway管理,服务本身不需要设置
# ================== Auth ====================
-urban-lifeline:
- auth:
- enabled: false # 认证服务自己不需要认证
- whitelist:
- - /** # 认证服务的所有接口都放行
+auth:
+ enabled: false # 认证服务自己不需要认证
+ gateway-mode: false # 不使用gateway模式(auth服务作为独立服务)
+ whitelist:
+ - /** # 认证服务的所有接口都放行
security:
aes:
- secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI= # Base64 编码,32字节(256位)
+ # AES-256 密钥(Base64编码,必须与所有服务保持一致)
+ # 警告:这是开发环境密钥,生产环境请使用密钥管理系统
+ secret-key: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=
# ================== Spring ==================
spring:
application:
diff --git a/urbanLifelineServ/bidding/src/main/resources/application.yml b/urbanLifelineServ/bidding/src/main/resources/application.yml
index 9a3c5047..f7b78cb8 100644
--- a/urbanLifelineServ/bidding/src/main/resources/application.yml
+++ b/urbanLifelineServ/bidding/src/main/resources/application.yml
@@ -1,8 +1,8 @@
# ================== Server ==================
server:
port: 8186
- servlet:
- context-path: /urban-lifeline/bidding
+ # servlet:
+ # context-path: /urban-lifeline/bidding # 微服务架构下,context-path由Gateway管理
# ================== Auth ====================
urban-lifeline:
diff --git a/urbanLifelineServ/common/common-dto/pom.xml b/urbanLifelineServ/common/common-dto/pom.xml
index 322216e2..4151742b 100644
--- a/urbanLifelineServ/common/common-dto/pom.xml
+++ b/urbanLifelineServ/common/common-dto/pom.xml
@@ -30,6 +30,11 @@
lombok
provided
+
+ org.xyzh.common
+ common-utils
+ ${urban-lifeline.version}
+
\ No newline at end of file
diff --git a/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/sys/TbSysUserDTO.java b/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/sys/TbSysUserDTO.java
index 1fedef41..c1d48c22 100644
--- a/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/sys/TbSysUserDTO.java
+++ b/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/sys/TbSysUserDTO.java
@@ -3,6 +3,10 @@ package org.xyzh.common.dto.sys;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.xyzh.common.dto.BaseDTO;
+import org.xyzh.common.utils.crypto.AesEncryptUtil;
+import org.xyzh.common.utils.crypto.EncryptedStringTypeHandler;
+import com.baomidou.mybatisplus.annotation.TableField;
+
import io.swagger.v3.oas.annotations.media.Schema;
/**
@@ -29,6 +33,7 @@ public class TbSysUserDTO extends BaseDTO {
@Schema(description = "邮箱")
private String email;
+ @TableField(typeHandler = EncryptedStringTypeHandler.class)
@Schema(description = "手机(加密)")
private String phone;
@@ -41,7 +46,10 @@ public class TbSysUserDTO extends BaseDTO {
@Schema(description = "用户状态")
private String status;
- @Schema(description = "用户类型")
- private String userType;
+
+ public void setPhone(String phone){
+ this.phone = phone;
+ this.phoneHash = AesEncryptUtil.maskPhone(phone);
+ }
}
\ No newline at end of file
diff --git a/urbanLifelineServ/common/common-utils/pom.xml b/urbanLifelineServ/common/common-utils/pom.xml
index 669ac175..9536c302 100644
--- a/urbanLifelineServ/common/common-utils/pom.xml
+++ b/urbanLifelineServ/common/common-utils/pom.xml
@@ -36,7 +36,10 @@
mybatis
provided
-
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
org.springframework.boot
diff --git a/urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/AesEncryptUtil.java b/urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/AesEncryptUtil.java
index 1c422a96..c7c84566 100644
--- a/urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/AesEncryptUtil.java
+++ b/urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/AesEncryptUtil.java
@@ -35,13 +35,24 @@ public class AesEncryptUtil {
* 从配置文件读取密钥,如果没有则生成新密钥
*/
public AesEncryptUtil(@Value("${security.aes.secret-key:}") String secretKeyString) {
- if (secretKeyString == null || secretKeyString.isEmpty()) {
- // 生产环境应该从配置中心或密钥管理系统获取
+ try {
+ if (secretKeyString == null || secretKeyString.isEmpty()) {
+ // 生产环境应该从配置中心或密钥管理系统获取
+ this.secretKey = generateKey();
+ System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key");
+ } else {
+ byte[] decodedKey = Base64.getDecoder().decode(secretKeyString);
+ if (decodedKey.length != 32) {
+ throw new IllegalArgumentException("AES-256 密钥长度必须是 32 字节,当前: " + decodedKey.length);
+ }
+ this.secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
+ System.out.println("✓ AES-256 加密工具初始化成功");
+ }
+ } catch (Exception e) {
+ System.err.println("❌ AES 密钥初始化失败: " + e.getMessage());
+ // 生成临时密钥以避免启动失败
this.secretKey = generateKey();
- System.err.println("警告: 未配置 AES 密钥,使用临时生成的密钥。生产环境请配置 security.aes.secret-key");
- } else {
- byte[] decodedKey = Base64.getDecoder().decode(secretKeyString);
- this.secretKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
+ System.err.println("已生成临时密钥,请尽快配置正确的 security.aes.secret-key");
}
}
@@ -169,9 +180,32 @@ public class AesEncryptUtil {
}
/**
- * 脱敏显示手机号
+ * 生成手机号Hash(用于数据库查询)
+ * 使用SHA-256生成固定Hash,相同手机号总是得到相同Hash
*/
public static String maskPhone(String phone) {
+ if (phone == null || phone.isEmpty()) {
+ return phone;
+ }
+ try {
+ java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
+ byte[] hash = digest.digest(phone.getBytes(java.nio.charset.StandardCharsets.UTF_8));
+ StringBuilder hexString = new StringBuilder();
+ for (byte b : hash) {
+ String hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1) hexString.append('0');
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ } catch (Exception e) {
+ throw new RuntimeException("生成手机号Hash失败", e);
+ }
+ }
+
+ /**
+ * 脱敏显示手机号(用于前端显示)
+ */
+ public static String maskPhoneDisplay(String phone) {
if (phone == null || phone.length() < 11) {
return phone;
}
@@ -187,4 +221,26 @@ public class AesEncryptUtil {
}
return idCard.substring(0, 6) + "********" + idCard.substring(14);
}
+
+ public static void main(String[] args) {
+ AesEncryptUtil aesEncryptUtil = new AesEncryptUtil("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=");
+ String phone = "17857100375";
+
+ // 测试加密(每次都不同,不能用于查询)
+ String encryptedPhone1 = aesEncryptUtil.encryptPhone(phone);
+ String encryptedPhone2 = aesEncryptUtil.encryptPhone(phone);
+ System.out.println("第一次加密: " + encryptedPhone1);
+ System.out.println("第二次加密: " + encryptedPhone2);
+ System.out.println("两次加密相同? " + encryptedPhone1.equals(encryptedPhone2));
+
+ // 测试Hash(用于查询,相同手机号总是得到相同Hash)
+ String hash1 = AesEncryptUtil.maskPhone(phone);
+ String hash2 = AesEncryptUtil.maskPhone(phone);
+ System.out.println("\n第一次Hash: " + hash1);
+ System.out.println("第二次Hash: " + hash2);
+ System.out.println("两次Hash相同? " + hash1.equals(hash2));
+
+ // 测试脱敏显示
+ System.out.println("\n脱敏显示: " + AesEncryptUtil.maskPhoneDisplay(phone));
+ }
}
diff --git a/urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/TypeHandlerConfig.java b/urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/TypeHandlerConfig.java
new file mode 100644
index 00000000..e7ea3fc4
--- /dev/null
+++ b/urbanLifelineServ/common/common-utils/src/main/java/org/xyzh/common/utils/crypto/TypeHandlerConfig.java
@@ -0,0 +1,37 @@
+package org.xyzh.common.utils.crypto;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Configuration;
+
+import jakarta.annotation.PostConstruct;
+
+/**
+ * TypeHandler 配置类
+ * 用于初始化 EncryptedStringTypeHandler 中的 AesEncryptUtil
+ *
+ * @author yslg
+ * @since 2025-12-11
+ */
+@Configuration
+@ConditionalOnClass(AesEncryptUtil.class)
+public class TypeHandlerConfig {
+
+ private final AesEncryptUtil aesEncryptUtil;
+
+ @Autowired(required = false)
+ public TypeHandlerConfig(AesEncryptUtil aesEncryptUtil) {
+ this.aesEncryptUtil = aesEncryptUtil;
+ }
+
+ @PostConstruct
+ public void init() {
+ // 初始化 TypeHandler 中的静态 AesEncryptUtil 实例
+ if (aesEncryptUtil != null) {
+ EncryptedStringTypeHandler.setAesEncryptUtil(aesEncryptUtil);
+ System.out.println("✓ TypeHandler 已初始化 AES 加密工具");
+ } else {
+ System.err.println("警告: AesEncryptUtil 未能注入,加密功能可能无法正常工作");
+ }
+ }
+}
diff --git a/urbanLifelineServ/crontab/src/main/resources/application.yml b/urbanLifelineServ/crontab/src/main/resources/application.yml
index 8450de15..f2258367 100644
--- a/urbanLifelineServ/crontab/src/main/resources/application.yml
+++ b/urbanLifelineServ/crontab/src/main/resources/application.yml
@@ -1,8 +1,8 @@
# ================== Server ==================
server:
port: 8189
- servlet:
- context-path: /urban-lifeline/crontab
+ # servlet:
+ # context-path: /urban-lifeline/crontab # 微服务架构下,context-path由Gateway管理
# ================== Auth ====================
urban-lifeline:
diff --git a/urbanLifelineServ/file/src/main/resources/application.yml b/urbanLifelineServ/file/src/main/resources/application.yml
index e29f64a6..dbcf13db 100644
--- a/urbanLifelineServ/file/src/main/resources/application.yml
+++ b/urbanLifelineServ/file/src/main/resources/application.yml
@@ -1,8 +1,8 @@
# ================== Server ==================
server:
port: 8184
- servlet:
- context-path: /urban-lifeline/file
+ # servlet:
+ # context-path: /urban-lifeline/file # 微服务架构下,context-path由Gateway管理
# ================== Auth ====================
urban-lifeline:
diff --git a/urbanLifelineServ/gateway/pom.xml b/urbanLifelineServ/gateway/pom.xml
index f356b573..cb587a66 100644
--- a/urbanLifelineServ/gateway/pom.xml
+++ b/urbanLifelineServ/gateway/pom.xml
@@ -28,19 +28,8 @@
org.springframework.boot
spring-boot-starter-logging
-
-
- org.springframework.cloud
- spring-cloud-gateway-server
-
-
-
-
- org.springframework.cloud
- spring-cloud-gateway-server-webflux
-
diff --git a/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/GatewayApplication.java b/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/GatewayApplication.java
index 5fde7dbb..d4e13b72 100644
--- a/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/GatewayApplication.java
+++ b/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/GatewayApplication.java
@@ -7,6 +7,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.xyzh.common.auth.config.SecurityConfig;
+import org.xyzh.common.auth.config.WebMvcConfig;
+import org.xyzh.common.auth.config.GatewayAuthConfig;
/**
* @description Gateway 网关启动类
@@ -23,8 +25,12 @@ import org.xyzh.common.auth.config.SecurityConfig;
"org.xyzh.common" // 公共模块(包括 common-auth)
},
excludeFilters = {
- // 排除 Spring MVC 的 SecurityConfig,Gateway 使用 WebFlux Security
- @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
+ // 排除 Spring MVC 相关配置,Gateway 使用 WebFlux
+ @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
+ SecurityConfig.class, // Spring MVC Security配置
+ WebMvcConfig.class, // Spring MVC配置
+ GatewayAuthConfig.class // 微服务Gateway模式配置(使用Servlet Filter)
+ })
}
)
public class GatewayApplication {
diff --git a/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/config/GatewaySecurityConfig.java b/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/config/GatewaySecurityConfig.java
new file mode 100644
index 00000000..2e168d07
--- /dev/null
+++ b/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/config/GatewaySecurityConfig.java
@@ -0,0 +1,32 @@
+package org.xyzh.gateway.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+import org.springframework.security.web.server.SecurityWebFilterChain;
+
+/**
+ * Gateway WebFlux Security 配置
+ * 完全禁用Spring Security的默认行为,由AuthGlobalFilter处理认证
+ *
+ * @author yslg
+ * @since 2025-12-11
+ */
+@Configuration
+@EnableWebFluxSecurity
+public class GatewaySecurityConfig {
+
+ @Bean
+ public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
+ return http
+ .csrf(ServerHttpSecurity.CsrfSpec::disable)
+ .formLogin(ServerHttpSecurity.FormLoginSpec::disable)
+ .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
+ .logout(ServerHttpSecurity.LogoutSpec::disable)
+ .authorizeExchange(exchange -> exchange
+ .anyExchange().permitAll() // 允许所有请求,由AuthGlobalFilter处理认证
+ )
+ .build();
+ }
+}
diff --git a/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/controller/GatewayDiagnosticController.java b/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/controller/GatewayDiagnosticController.java
new file mode 100644
index 00000000..698388e8
--- /dev/null
+++ b/urbanLifelineServ/gateway/src/main/java/org/xyzh/gateway/controller/GatewayDiagnosticController.java
@@ -0,0 +1,59 @@
+package org.xyzh.gateway.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.gateway.route.Route;
+import org.springframework.cloud.gateway.route.RouteLocator;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Gateway诊断控制器 - 用于检查路由配置
+ *
+ * @author yslg
+ * @since 2025-12-11
+ */
+@RestController
+@RequestMapping("/gateway-diagnostic")
+public class GatewayDiagnosticController {
+
+ @Autowired
+ private RouteLocator routeLocator;
+
+ /**
+ * 获取所有路由信息
+ * 访问: http://localhost:8180/gateway-diagnostic/routes
+ */
+ @GetMapping("/routes")
+ public Flux