# Difywork **Repository Path**: zouwei1815/difywork ## Basic Information - **Project Name**: Difywork - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-09 - **Last Updated**: 2026-07-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Dify 工作流查看权限服务(perm-service) 为 [Dify](https://dify.ai) 工作流(App)提供**查看权限**管理,零侵入 Dify 源码。 ## 架构 ``` ┌─────────┐ ┌──────────────────────────┐ ┌────────────────┐ │ Dify Web│────►│ Nginx (OpenResty) │────►│ Dify Console │ └─────────┘ │ ├ access_by_lua: 鉴权 │ │ API(不动) │ │ ├ body_filter: 过滤 │ └────────────────┘ │ └ 失败 → 403 │ └──────────┬───────────────┘ │ /internal/visible-apps ▼ ┌──────────────────────────┐ │ perm-service(本项目) │ │ Spring Boot 2.7.18 │ │ MySQL 8.0 + Dify PG(RO) │ └──────────────────────────┘ ``` ## 技术栈 | 组件 | 版本 | |---|---| | JDK | 8 | | Spring Boot | 2.7.18 | | MySQL | 8.0(主库 `dify_perm`) | | PostgreSQL | Dify 数据库(只读) | | Flyway | 9.22 | | JJWT | 0.11.5 | | springdoc-openapi | 1.7.0 | | Maven | 3.9+ | ## 快速启动 ### 1. 环境要求 - JDK 8 - Maven 3.9+ - MySQL 8.0(运行中) - Dify PostgreSQL(运行中) ### 2. 建库 ```sql -- MySQL 中执行 CREATE DATABASE IF NOT EXISTS dify_perm DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; ``` > Flyway 启动时会自动建表,无需手动执行 SQL。 > 如需手动建表:`mysql --default-character-set=utf8mb4 -u root -p dify_perm < src/main/resources/db/migration/V1__init_schema.sql` ### 3. 修改配置 编辑 `src/main/resources/application.yml`: ```yaml # MySQL 主库 perm: datasource: url: jdbc:mysql://localhost:3306/dify_perm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&createDatabaseIfNotExist=true username: root password: <你的密码> internal-token: ${PERM_INTERNAL_TOKEN:perm-dev-token-change-me} # Dify PG 只读 dify: datasource: url: jdbc:postgresql://:5432/dify username: postgres password: <你的密码> jwt-secret: ${DIFY_SECRET_KEY:} # 从 Dify .env 获取 SECRET_KEY ``` ### 4. 启动 ```bash # 编译 mvn clean package -DskipTests # 运行 java -jar target/difyDemo-1.0-SNAPSHOT.jar # 或 Maven 插件启动 mvn spring-boot:run ``` ### 5. 验证 ```bash # 健康检查 curl http://localhost:8090/actuator/health # → {"status":"UP"} # Swagger UI # 浏览器打开 http://localhost:8090/swagger-ui.html ``` ## 环境变量 | 变量 | 必填 | 默认值 | 说明 | |---|---|---|---| | `PERM_DB_PASSWORD` | 否 | yml 中明文(开发) | MySQL 主库密码(生产用环境变量) | | `DIFY_RO_PASSWORD` | 否 | yml 中明文(开发) | Dify PG 只读密码 | | `DIFY_SECRET_KEY` | 是 | 空 | Dify 的 SECRET_KEY,用于解析 JWT | | `PERM_INTERNAL_TOKEN` | 否 | `perm-dev-token-change-me` | Nginx 调 /internal/** 的预共享密钥 | ## 数据库表结构(6 张表) | 表 | 说明 | |---|---| | `perm_role` | 角色定义(租户内唯一名) | | `perm_account_role` | 账号 ↔ 角色(M:N) | | `perm_role_app` | 角色 ↔ 工作流(M:N) | | `perm_account_app` | 账号直授兜底(allow/deny + 过期时间) | | `perm_tenant_policy` | 租户策略(whitelist/blacklist + admin 豁免) | | `perm_audit_log` | 审计日志 | ## 权限计算优先级 ``` 1. owner/admin 豁免(bypass_admin=true) → 全部可见 2. 账号直授 deny → 强制不可见 3. 账号直授 allow → 强制可见 4. 角色授权(账号→角色→App) → 累加到可见集 5. 默认策略(whitelist=不可见 / blacklist=可见) ``` ## API 接口(23 个) ### 内部接口(给 Nginx 调用,Header: `X-Internal-Token`) | Method | Path | 说明 | |---|---|---| | GET | `/internal/visible-apps?accountId=&tenantId=` | 核心:查可见工作流 | | GET | `/internal/whoami` | 解析 Dify JWT | | GET | `/internal/health` | 轻量健康检查 | ### 后台管理接口(Header: `Authorization: Bearer ` + `X-WORKSPACE-ID`) | Method | Path | 说明 | |---|---|---| | POST | `/api/v1/roles` | 创建角色 | | GET | `/api/v1/roles?tenantId=` | 角色列表 | | GET | `/api/v1/roles/{id}` | 角色详情 | | PATCH | `/api/v1/roles/{id}` | 修改角色 | | DELETE | `/api/v1/roles/{id}?force=` | 删除角色 | | GET | `/api/v1/roles/{id}/apps` | 角色可见 App | | PUT | `/api/v1/roles/{id}/apps` | 批量覆盖授权 | | POST | `/api/v1/roles/{id}/apps/{appId}` | 追加授权 | | DELETE | `/api/v1/roles/{id}/apps/{appId}` | 移除授权 | | GET | `/api/v1/accounts/{id}/roles?tenantId=` | 账号绑定的角色 | | PUT | `/api/v1/accounts/{id}/roles` | 批量覆盖绑定 | | GET | `/api/v1/accounts/{id}/apps?tenantId=` | 账号直授列表 | | PUT | `/api/v1/accounts/{id}/apps` | 批量覆盖直授 | | POST | `/api/v1/accounts/{id}/apps/{appId}` | 追加/修改直授 | | DELETE | `/api/v1/accounts/{id}/apps/{appId}?tenantId=` | 撤销直授 | | GET | `/api/v1/tenants/{id}/policy` | 查看租户策略 | | PUT | `/api/v1/tenants/{id}/policy` | 修改租户策略 | | GET | `/api/v1/dify/accounts` | 搜索 Dify 账号 | | GET | `/api/v1/dify/apps?tenantId=` | 搜索 Dify 工作流 | | GET | `/api/v1/audit` | 审计日志查询 | > 完整参数说明见 Swagger UI:`http://localhost:8090/swagger-ui.html` ## 鉴权方式 | 路径 | 方式 | 说明 | |---|---|---| | `/internal/**` | `X-Internal-Token` Header | Nginx ↔ 权限服务预共享密钥 | | `/api/v1/**` | `Authorization: Bearer ` | 复用 Dify Console API 的 access_token | | `/actuator/**` | 无 | 公开(生产建议收紧到内网) | | `/swagger-ui/**` | 无 | 公开(生产建议关闭) | ## 项目结构 ``` src/main/java/org/example/perm/ ├── config/ ← 配置(双数据源/Security/Cache/OpenAPI/定时任务/Metrics) ├── common/ ← 通用(ApiResponse/ErrorCode/BizException/GlobalExceptionHandler/AuditAspect) ├── security/ ← 安全(DifyJwtParser/JwtAuthFilter/InternalTokenFilter/CurrentUser) ├── domain/ │ ├── perm/ ← MySQL 主库实体(6 个) │ └── dify/ ← Dify PG 只读实体(3 个,@Immutable) ├── repository/ │ ├── perm/ ← 主库 Repository(6 个) │ └── dify/ ← Dify 只读 Repository(3 个) ├── service/ ← 业务服务(8 个) ├── controller/ ← REST 接口(8 个 Controller,23 个接口) └── dto/ ├── request/ ← 请求 DTO(6 个) └── response/ ← 响应 DTO(7 个) ``` ## Docker 部署 ```bash # 构建镜像 docker build -t perm-service:1.0.0 . # 运行 docker run -d --name perm-service -p 8090:8090 \ -e PERM_DB_PASSWORD=xxx \ -e DIFY_RO_PASSWORD=xxx \ -e DIFY_SECRET_KEY=xxx \ -e PERM_INTERNAL_TOKEN=xxx \ perm-service:1.0.0 ``` ### 本地开发(Docker Compose) ```bash # 起 MySQL + Redis(如果你本地没有) docker-compose -f docker-compose.dev.yml up -d ``` ## Postman 导入 `postman/` 目录下的文件即可: - `perm-service.postman_collection.json` — 23 个请求 - `perm-service-dev.postman_environment.json` — 开发环境变量 ## 常见问题 ### Q: 启动报 `Failed to configure a DataSource` A: 检查 MySQL 是否运行、`application.yml` 中连接信息是否正确。 ### Q: 启动报 `Schema-validation: missing table` A: Flyway 未执行或建库时字符集不对。手动执行: ```bash mysql --default-character-set=utf8mb4 -u root -p dify_perm < src/main/resources/db/migration/V1__init_schema.sql ``` ### Q: Dify PG 连不上 A: 检查 Dify PostgreSQL 是否运行、`dify.datasource.*` 配置是否正确。如果暂时没有 Dify PG,可在 `DifyDataSourceConfig` 上加 `@ConditionalOnProperty(name = "dify.datasource.url")` 跳过。 ### Q: JWT 解析失败 A: 确认 `dify.jwt-secret` 配置的值与 Dify 部署时的 `SECRET_KEY` 一致。获取方式: ```bash grep SECRET_KEY /path/to/dify/docker/.env ``` ### Q: 表里的 COMMENT 注释是乱码 A: MySQL 客户端连接时加 `--default-character-set=utf8mb4`。数据库实际存储是正确的 UTF-8。