From 54d4e14761b12b6b85c7fac72ba586aa31e886e1 Mon Sep 17 00:00:00 2001
From: zhuangtianxiang <2913129173@qq.com>
Date: Mon, 28 Apr 2025 00:09:31 +0800
Subject: [PATCH] =?UTF-8?q?feat(security):=20=E5=AE=9E=E7=8E=B0=E5=9F=BA?=
=?UTF-8?q?=E4=BA=8E=20Spring=20WebFlux=20=E7=9A=84=E7=94=A8=E6=88=B7?=
=?UTF-8?q?=E8=AE=A4=E8=AF=81=E5=92=8C=E6=9D=83=E9=99=90=E7=AE=A1=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 ReactiveUserDetailsService 实现类 FluxUserDetailServiceImpl- 添加 MenuFluxRepository、RoleFluxRepository、UserFluxRepository 和 UserRoleFluxRepository 接口
- 实现 SpringWebFluxSecurityConfig 配置类
- 在 V1ChatController、V1DatasetController、V1ServerController 和 V1WorkflowController 中添加权限控制注解
- 更新 DeptService接口,新增 listFluxTree 方法
---
pom.xml | 9 ++
.../security/JpaUserDetailsServiceImpl.java | 2 +
.../security/SpringSecurityConfig.java | 1 -
.../flux/FluxUserDetailServiceImpl.java | 83 ++++++++++++++
.../flux/SpringWebFluxSecurityConfig.java | 102 ++++++++++++++++++
.../dify/controller/V1ChatController.java | 7 +-
.../dify/controller/V1DatasetController.java | 9 ++
.../dify/controller/V1ServerController.java | 9 ++
.../dify/controller/V1WorkflowController.java | 4 +
.../dify/modules/system/entity/UserRole.java | 5 +-
.../system/repo/flux/MenuFluxRepository.java | 16 +++
.../system/repo/flux/RoleFluxRepository.java | 15 +++
.../system/repo/flux/UserFluxRepository.java | 12 +++
.../repo/flux/UserRoleFluxRepository.java | 16 +++
.../modules/system/service/DeptService.java | 4 +
.../system/service/impl/DeptServiceImpl.java | 37 ++++++-
src/main/resources/application-dev.yml | 9 +-
.../service/impl/MenuServiceImplTest.java | 57 +++++-----
18 files changed, 360 insertions(+), 37 deletions(-)
create mode 100644 src/main/java/com/zsc/edu/dify/framework/security/flux/FluxUserDetailServiceImpl.java
create mode 100644 src/main/java/com/zsc/edu/dify/framework/security/flux/SpringWebFluxSecurityConfig.java
create mode 100644 src/main/java/com/zsc/edu/dify/modules/system/repo/flux/MenuFluxRepository.java
create mode 100644 src/main/java/com/zsc/edu/dify/modules/system/repo/flux/RoleFluxRepository.java
create mode 100644 src/main/java/com/zsc/edu/dify/modules/system/repo/flux/UserFluxRepository.java
create mode 100644 src/main/java/com/zsc/edu/dify/modules/system/repo/flux/UserRoleFluxRepository.java
diff --git a/pom.xml b/pom.xml
index 6cae0c1..ef39dfe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -119,6 +119,15 @@
true
+
+ org.springframework.boot
+ spring-boot-starter-data-r2dbc
+
+
+ io.r2dbc
+ r2dbc-postgresql
+ 0.8.13.RELEASE
+
org.mapstruct
mapstruct
diff --git a/src/main/java/com/zsc/edu/dify/framework/security/JpaUserDetailsServiceImpl.java b/src/main/java/com/zsc/edu/dify/framework/security/JpaUserDetailsServiceImpl.java
index 0570adb..a3adedb 100644
--- a/src/main/java/com/zsc/edu/dify/framework/security/JpaUserDetailsServiceImpl.java
+++ b/src/main/java/com/zsc/edu/dify/framework/security/JpaUserDetailsServiceImpl.java
@@ -6,10 +6,12 @@ import com.zsc.edu.dify.modules.system.entity.*;
import com.zsc.edu.dify.modules.system.repo.*;
import com.zsc.edu.dify.modules.system.service.DeptService;
import com.zsc.edu.dify.modules.system.service.RoleService;
+import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
diff --git a/src/main/java/com/zsc/edu/dify/framework/security/SpringSecurityConfig.java b/src/main/java/com/zsc/edu/dify/framework/security/SpringSecurityConfig.java
index ea6d687..dcb04a9 100644
--- a/src/main/java/com/zsc/edu/dify/framework/security/SpringSecurityConfig.java
+++ b/src/main/java/com/zsc/edu/dify/framework/security/SpringSecurityConfig.java
@@ -24,7 +24,6 @@ import javax.sql.DataSource;
/**
* @author harry_yao
*/
-//@EnableWebFluxSecurity
@AllArgsConstructor
@EnableMethodSecurity
@Configuration
diff --git a/src/main/java/com/zsc/edu/dify/framework/security/flux/FluxUserDetailServiceImpl.java b/src/main/java/com/zsc/edu/dify/framework/security/flux/FluxUserDetailServiceImpl.java
new file mode 100644
index 0000000..338964f
--- /dev/null
+++ b/src/main/java/com/zsc/edu/dify/framework/security/flux/FluxUserDetailServiceImpl.java
@@ -0,0 +1,83 @@
+package com.zsc.edu.dify.framework.security.flux;
+import com.zsc.edu.dify.common.util.TreeUtil;
+import com.zsc.edu.dify.exception.StateException;
+import com.zsc.edu.dify.framework.security.UserDetailsImpl;
+import com.zsc.edu.dify.modules.system.entity.Dept;
+import com.zsc.edu.dify.modules.system.entity.Menu;
+import com.zsc.edu.dify.modules.system.entity.Role;
+import com.zsc.edu.dify.modules.system.entity.UserRole;
+import com.zsc.edu.dify.modules.system.repo.flux.*;
+import com.zsc.edu.dify.modules.system.service.DeptService;
+import lombok.AllArgsConstructor;
+import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author zhuang
+ */
+@AllArgsConstructor
+@Service
+public class FluxUserDetailServiceImpl implements ReactiveUserDetailsService {
+
+ private final UserFluxRepository userRepo;
+ private final MenuFluxRepository menuRepository;
+ private final RoleFluxRepository roleFluxRepository;
+ private final UserRoleFluxRepository userRoleFluxRepository;
+ private final DeptService deptService;
+ @Override
+ public Mono findByUsername(String username) {
+ return userRepo.findByUsername(username)
+ .flatMap(user -> {
+ if (!user.getEnableState()) {
+ return Mono.error(new StateException("用户 '" + username + "' 已被禁用!请联系管理员"));
+ }
+ // 先获取UserRole列表,并从中提取roleIds
+ return userRoleFluxRepository.findByUserId(user.getId()).collectList()
+ .flatMap(userRoles -> Mono.zip(
+ roleFluxRepository.findByDeptId(user.getDeptId()),
+ deptService.listFluxTree(user.getDeptId()),
+ menuRepository.findByRoleId(user.getRoleId())
+ ))
+ .flatMap(tuple -> {
+ Role role = (Role) tuple.getT1();
+ List depts = (List) tuple.getT2();
+ List