{"role":"user","message":{"content":[{"type":"text","text":"\nExplore the gateway module under /Users/kazusa/IdeaProjects/baoshi/wms/ to understand the authentication and authorization logic. Specifically find:\n\n1. The gateway module directory structure\n2. How the gateway validates JWT tokens or session tokens\n3. The authentication filter/interceptor code\n4. Token parsing logic - what fields are in the token, how it's verified\n5. What headers the gateway passes to downstream services after auth\n6. Any auth configuration (which paths are public/protected)\n7. The token/JWT related utility classes\n\nAlso check /Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/ for any auth-related utility classes (AuthContext, token utils, etc.)\n\nReturn all relevant file contents and paths.\n"}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"正在探索 gateway 模块的认证和授权逻辑。先定位 gateway 模块的位置和结构。"}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"读取关键文件以了解认证和授权逻辑:"}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"查找更多相关配置和常量文件:"}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"读取常量文件和枚举类:"}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"查看 gateway 模块的目录结构和配置文件:"}]}} {"role":"assistant","message":{"content":[{"type":"text","text":"## Gateway 模块认证和授权逻辑分析报告\n\n### 1. Gateway 模块目录结构\n\nGateway 模块位于:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-gateway-service/baoshi-gateway-server/`\n\n主要文件结构:\n```\nbaoshi-gateway-server/\n├── src/main/java/com/baoshi/gateway/server/\n│ ├── filter/\n│ │ ├── UserGlobalFilter.java # 主要认证过滤器\n│ │ └── GateWayWebFilter.java # Web过滤器(空实现)\n│ ├── util/\n│ │ ├── AuthenticationUtil.java # 认证工具类(白名单验证)\n│ │ └── PermissionUtil.java # 权限验证工具类\n│ ├── config/\n│ │ ├── GatewayConfig.java # 网关配置\n│ │ ├── CorsConfig.java # CORS配置\n│ │ └── ApplicationConfig.java\n│ ├── exceptions/\n│ │ └── GatewayExceptionHandler.java # 异常处理\n│ └── GatewayApplication.java # 启动类\n```\n\n### 2. JWT Token 验证逻辑\n\n#### 2.1 Token 验证流程(UserGlobalFilter.java)\n\n主要验证步骤(第120-146行):\n1. 检查请求来源(Source header)是否有效\n2. 检查是否携带 token(Authorization header)\n3. 使用 `JwtUtil.verifyAndGet()` 验证 JWT 签名和有效性\n4. 从 JWT 的 `subject` 字段提取用户ID\n5. 构建 Redis key:`user:{type}:{userId}`\n6. 检查 Redis 中是否存在用户信息\n7. 验证 Redis 中的 token 是否与请求的 token 一致(防止重复登录)\n\n#### 2.2 JWT Token 结构(JwtUtil.java)\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common/src/main/java/com/baoshi/common/util/JwtUtil.java`\n\nJWT 字段:\n- `id`: UUID(JWT ID)\n- `subject`: 用户ID(String)\n- `issuedAt`: 签发时间\n- `expiration`: 过期时间\n- 签名算法:HS256\n- 密钥:`\"SWMS-JWT\"`(硬编码)\n\nToken 创建方法(第21-31行):\n```java\npublic static String create(User user, Long expireVal) {\n Date date = new Date();\n return Jwts.builder()\n .setId(UUID.randomUUID().toString())\n .setSubject(String.valueOf(user.getId()))\n .setIssuedAt(date)\n .setExpiration(new Date(date.getTime() + expireVal))\n .signWith(SignatureAlgorithm.HS256, SECRET)\n .compact();\n}\n```\n\n### 3. 认证过滤器/拦截器\n\n#### 3.1 UserGlobalFilter(主要认证过滤器)\n\n文件:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-gateway-service/baoshi-gateway-server/src/main/java/com/baoshi/gateway/server/filter/UserGlobalFilter.java`\n\n核心逻辑(第72-109行):\n1. 获取请求信息:IP、路径、token、来源类型、版本号\n2. SSE 请求直接放行\n3. 白名单检查(IP、URL、IP-URL 组合)\n4. 非白名单请求进行 token 验证\n5. 验证通过后设置用户上下文(AuthContext)\n6. 添加自定义请求头传递给下游服务\n7. WEB 来源请求进行权限验证\n\n### 4. Token 解析逻辑\n\n#### 4.1 JWT 解析(JwtUtil.java)\n\n验证方法(第33-39行):\n```java\npublic static Claims verifyAndGet(String token) {\n try{\n return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();\n }catch (Exception e) {\n return null;\n }\n}\n```\n\n解析出的字段:\n- `subject`: 用户ID(用于构建 Redis key)\n- `issuedAt`: 签发时间\n- `expiration`: 过期时间\n- `id`: JWT ID\n\n#### 4.2 Redis 用户信息结构\n\nRedis Key 格式:`user:{source}:{userId}`\n\n例如:`user:WEB:123`、`user:APP:456`\n\n存储内容:User 对象的 JSON 字符串,包含:\n- `id`: 用户ID\n- `source`: 请求来源(WEB/APP/CUSTOMER等)\n- `token`: 当前 token\n- `username`: 用户名\n- `role`: 角色\n- `dataPermission`: 数据权限\n- `version`: 版本号\n- 其他字段\n\n### 5. 传递给下游服务的 Headers\n\n在 `UserGlobalFilter` 中(第95-97行),网关会添加以下请求头:\n\n1. `User-Key`: Redis 用户信息 key(格式:`user:{source}:{userId}`)\n2. `Version`: 客户端版本号\n\n注意:原始的 `Authorization` 和 `Source` 头也会传递给下游服务(通过 FeignTenantInterceptor)。\n\n#### 5.1 FeignTenantInterceptor(微服务间调用)\n\n文件:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common-micro-spring-boot-starter/src/main/java/com/baoshi/micro/config/FeignTenantInterceptor.java`\n\n在微服务间调用时,会添加以下请求头(第55-58行):\n- `Authorization`: 用户 token\n- `Source`: 请求来源\n- `Version`: 版本号\n- `User-Key`: Redis key\n- `X-Trace-Id`: 链路追踪ID\n\n#### 5.2 UserFilter(下游服务过滤器)\n\n文件:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common-micro-spring-boot-starter/src/main/java/com/baoshi/micro/filter/UserFilter.java`\n\n下游服务从请求头读取:\n- `User-Key`: 从 Redis 获取用户信息并设置到 `AuthContext`\n- `Version`: 设置到用户对象\n- `X-Trace-Id`: 设置链路追踪ID\n\n### 6. 认证配置(公开/受保护路径)\n\n#### 6.1 白名单配置(UrlWhiteConsts.java)\n\n文件:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common/src/main/java/com/baoshi/common/constant/UrlWhiteConsts.java`\n\n三种白名单机制:\n\n1. IP 白名单(第168-170行):\n - `58.33.243.165`\n\n2. URL 白名单(第18-163行):\n 按服务前缀配置,例如:\n - `api/user`: login, loginApp, check 等\n - `api/erp`: check, we-chat/*, waybill/push 等\n - `api/robot`: external/hk/*, external/zs/* 等\n - 支持通配符 `*`\n\n3. IP-URL 组合白名单(第177-194行):\n - 特定 IP 访问特定路径\n - 例如:`47.103.131.176` → `/oapi/device/check/waybill/create`\n\n#### 6.2 白名单验证逻辑(AuthenticationUtil.java)\n\n文件:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-gateway-service/baoshi-gateway-server/src/main/java/com/baoshi/gateway/server/util/AuthenticationUtil.java`\n\n- `routeAuth(path)`: 检查路径是否在白名单\n- `ipRouteAuth(ip, path)`: 检查 IP-URL 组合是否在白名单\n- 支持路径通配符匹配\n\n### 7. Token/JWT 相关工具类\n\n#### 7.1 JwtUtil\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common/src/main/java/com/baoshi/common/util/JwtUtil.java`\n\n功能:\n- `create(User user, Long expireVal)`: 创建 JWT token\n- `verifyAndGet(String token)`: 验证并解析 JWT\n\n#### 7.2 TokenUtils\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common-data/src/main/java/com/baoshi/basis/util/TokenUtils.java`\n\n功能:\n- `getUser(Long user, ServerEnum server)`: 从 Redis 获取用户信息\n- `setUser(ServerEnum server, User user)`: 保存用户信息到 Redis\n- `refresh()`: 刷新 token\n- `verifyAndGetUser(String token, ServerEnum server)`: 验证 token 并获取用户\n\n#### 7.3 AuthContext\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common/src/main/java/com/baoshi/common/system/AuthContext.java`\n\n功能:\n- `getUser()`: 获取当前线程用户信息(ThreadLocal)\n- `setUser(User info)`: 设置用户信息\n- `removeUser()`: 清除用户信息\n- `isAdmin()`: 判断是否为管理员\n- `getDataPermission()`: 获取数据权限\n- `hasWarehouseDataPermission()`: 检查仓库权限\n- `hasOwnerDataPermission()`: 检查货主权限\n\n### 8. 相关常量类\n\n#### 8.1 CustomHttpHeaderConsts\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common/src/main/java/com/baoshi/common/constant/CustomHttpHeaderConsts.java`\n\n定义的请求头:\n- `SOURCE = \"Source\"`: 请求来源\n- `USER_KEY = \"User-Key\"`: 用户标识 key\n- `MESSAGE_ID = \"Message-Id\"`: 幂等ID\n- `VERSION = \"Version\"`: 系统版本\n- `TRACE_ID = \"X-Trace-Id\"`: 链路追踪ID\n\n#### 8.2 RedisConsts\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common/src/main/java/com/baoshi/common/constant/RedisConsts.java`\n\n相关方法:\n- `USER_KEY(String id, String type)`: 构建用户 Redis key\n- `USER_PER_KEY(Long id, String method)`: 构建用户权限 key\n- `USER_PUB_PER(String method)`: 构建公共权限 key\n\n#### 8.3 ServerEnum\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-common/common/src/main/java/com/baoshi/common/eum/ServerEnum.java`\n\n支持的请求来源:\n- `WEB`: 24小时过期\n- `CUSTOMER`: 24小时过期\n- `APP`: 7天过期\n- `OTHER`: 30天过期\n- `CRM`: 24小时过期\n- `TOOL`: 30天过期\n\n### 9. 权限验证逻辑\n\n#### PermissionUtil.java\n\n位置:`/Users/kazusa/IdeaProjects/baoshi/wms/baoshi-gateway-service/baoshi-gateway-server/src/main/java/com/baoshi/gateway/server/util/PermissionUtil.java`\n\n验证流程(第44-64行):\n1. 超级管理员直接通过\n2. 检查公共权限(Redis key: `user:permission:public:{method}`)\n3. 检查个人权限(Redis key: `user:{method}:{userId}`)\n4. 支持路径通配符匹配\n\n### 总结\n\n认证授权流程:\n1. 请求到达网关 → `UserGlobalFilter` 拦截\n2. 检查白名单(IP/URL/IP-URL)\n3. 非白名单请求验证 JWT token\n4. 从 Redis 获取用户信息并验证\n5. 设置用户上下文(AuthContext)\n6. 添加 `User-Key` 和 `Version` 请求头\n7. WEB 来源请求进行权限验证\n8. 请求转发到下游服务\n9. 下游服务通过 `UserFilter` 从 `User-Key` 恢复用户信息\n\n关键文件路径已列出,可直接查看完整代码。"}]}}