From 0b3c1f59e52fd74e92ae476cd932cf19fc5d3760 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Mon, 14 Jul 2025 20:34:16 +0800 Subject: [PATCH] =?UTF-8?q?:memo:=20=E6=B7=BB=E5=8A=A0=E3=80=90=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E8=A7=92=E8=89=B2=E4=B8=8E=E6=9D=83=E9=99=90=E3=80=91?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spring-security/ReadMe.md | 211 ++++++++++++++++-- .../images/image-20250714202213150.png | Bin 0 -> 40446 bytes .../security/service/DbUserDetailService.java | 2 +- 3 files changed, 189 insertions(+), 24 deletions(-) create mode 100644 spring-security/images/image-20250714202213150.png diff --git a/spring-security/ReadMe.md b/spring-security/ReadMe.md index 3f2ea70..e1d2e5b 100644 --- a/spring-security/ReadMe.md +++ b/spring-security/ReadMe.md @@ -1,5 +1,7 @@ # Spring Security 6 入门指南 +![image-20250714202213150](./images/image-20250714202213150.png) + ## 基本配置 ### 添加依赖 @@ -403,6 +405,24 @@ public UserDetails getCurrentUserDetail() { ### 角色与权限配置 +> [!IMPORTANT] +> +> 1. **角色与权限的区别**: +> - `hasRole()`会自动添加"ROLE_"前缀 +> - `hasAuthority()`直接使用指定的权限字符串 +> 2. **匹配顺序**: +> - Spring Security会按照配置的顺序进行匹配 +> - 更具体的路径应该放在前面,通用规则(如anyRequest)放在最后 +> 3. **方法选择建议**: +> - `hasRole()`/`hasAnyRole()`:适合基于角色的访问控制 +> - `hasAuthority()`/`hasAnyAuthority()`:适合更细粒度的权限控制 +> - `authenticated()`:只需认证通过,不检查具体角色/权限 +> - `permitAll()`:完全开放访问 +> 4. **最佳实践**: +> - 对于REST API,通常使用`authenticated()`配合方法级权限控制 +> - 静态资源应明确配置`permitAll()` +> - 生产环境不建议使用`anyRequest().permitAll()` + #### 1. 基于角色的URL访问控制 ##### 单角色配置 @@ -517,27 +537,26 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception { } ``` -### 重要说明 +### 基于方法的授权 -1. **角色与权限的区别**: - - `hasRole()`会自动添加"ROLE_"前缀 - - `hasAuthority()`直接使用指定的权限字符串 -2. **匹配顺序**: - - Spring Security会按照配置的顺序进行匹配 - - 更具体的路径应该放在前面,通用规则(如anyRequest)放在最后 -3. **方法选择建议**: - - `hasRole()`/`hasAnyRole()`:适合基于角色的访问控制 - - `hasAuthority()`/`hasAnyAuthority()`:适合更细粒度的权限控制 - - `authenticated()`:只需认证通过,不检查具体角色/权限 - - `permitAll()`:完全开放访问 -4. **最佳实践**: - - 对于REST API,通常使用`authenticated()`配合方法级权限控制 - - 静态资源应明确配置`permitAll()` - - 生产环境不建议使用`anyRequest().permitAll()` +> [!NOTE] +> +> 通过在任何 `@Configuration` 类上添加 `@EnableMethodSecurity` 注解。 +> +> Spring Boot Starter Security 默认情况下不会激活方法级别的授权。 + +#### 提供的注解 + +1. @PreAuthorize +2. @PostAuthorize +3. @PreFilter +4. @PostFilter ## 关于UserDetailsService的深入解析 -### 1. UserDetailsService的核心作用 +### 简单阐述 + +#### 1. UserDetailsService的核心作用 `UserDetailsService`是Spring Security的核心接口,负责提供用户认证数据。它只有一个核心方法: @@ -547,7 +566,7 @@ UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 当用户尝试登录时,Spring Security会自动调用这个方法来获取用户详情。 -### 2. 为什么不需要手动校验密码? +#### 2. 为什么不需要手动校验密码? 在标准的表单登录流程中,Spring Security的认证流程会自动处理密码校验,这是因为: @@ -568,7 +587,7 @@ UserDetails loadUserByUsername(String username) throws UsernameNotFoundException D --> E[认证成功/失败] ``` -### 3. 完整的安全配置示例 +#### 3. 完整的安全配置示例 ```java @Configuration @@ -609,7 +628,7 @@ public class SecurityConfig { } ``` -### 4. 关键注意事项 +#### 4. 关键注意事项 1. **必须提供PasswordEncoder**: 如果没有配置,会出现`There is no PasswordEncoder mapped`错误 @@ -635,7 +654,7 @@ public class SecurityConfig { - 存在`PasswordEncoder` bean - 没有显式配置`AuthenticationManager` -### 5. 扩展场景 +#### 5. 扩展场景 如果需要自定义认证逻辑(如增加验证码校验),可以: @@ -671,7 +690,7 @@ public class CustomAuthProvider implements AuthenticationProvider { http.authenticationProvider(customAuthProvider); ``` -### 总结对比表 +#### 总结对比表 | 场景 | 需要手动处理 | 自动处理 | | ------------ | ---------------------------------- | ----------------------- | @@ -680,4 +699,150 @@ http.authenticationProvider(customAuthProvider); | 账号状态检查 | 通过`UserDetails`返回的状态 | ✅ | | 权限加载 | 通过`UserDetails.getAuthorities()` | ✅ | -这样设计的好处是:开发者只需关注业务数据获取(用户信息查询),安全相关的校验逻辑由框架统一处理,既保证了安全性又减少了重复代码。 \ No newline at end of file +这样设计的好处是:开发者只需关注业务数据获取(用户信息查询),安全相关的校验逻辑由框架统一处理,既保证了安全性又减少了重复代码。 + +### 获取角色与权限 + +#### 1. 角色信息处理 + +在`UserDetailsService`实现中获取并设置用户角色: + +```java +@Override +public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 1. 查询用户基本信息 + UserEntity userEntity = userMapper.selectByUsername(username); + if (userEntity == null) { + throw new UsernameNotFoundException("用户不存在"); + } + + // 2. 获取角色信息(自动添加ROLE_前缀) + String[] roles = findUserRolesByUserId(userEntity.getId()); + + // 3. 获取权限信息 + List permissions = findPermissionsByUserId(userEntity.getId()); + + return User.builder() + .username(userEntity.getUsername()) + .password(userEntity.getPassword()) + // 角色会自动添加ROLE_前缀 + .roles(roles) + // 直接作为权限字符串使用 + .authorities(permissions.toArray(new String[0])) + .build(); +} +``` + +**关键说明**: + +- `roles()`方法会自动为角色添加`ROLE_`前缀(如`ADMIN`会变成`ROLE_ADMIN`) +- 角色和权限在Spring Security中是不同概念,角色本质是带有特殊前缀的权限 + +#### 2. 权限信息处理(两种方式) + +**方式一:直接使用字符串** + +```java +List permissions = findPermissionsByUserId(userId); +return User.withUsername(username) + .authorities(permissions.toArray(new String[0])) + // ... + .build(); +``` + +**方式二:转换为SimpleGrantedAuthority** + +```java +List authorities = permissions.stream() + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + +return User.withUsername(username) + .authorities(authorities) + // ... + .build(); +``` + +**权限实现类对比**: + +| 实现类 | 适用场景 | 特点 | +| ---------------------------- | ------------- | ---------------- | +| `SimpleGrantedAuthority` | 普通权限/角色 | 最常用实现 | +| `SwitchUserGrantedAuthority` | 用户切换场景 | 包含原始用户信息 | +| `JaasGrantedAuthority` | JAAS集成 | 用于Java认证服务 | + +#### 3. Mapper配置优化 + +**角色查询Mapper**: + +```xml + +``` + +**权限查询Mapper**: + +```xml + +``` + +#### 4. 重要注意事项 + +1. **角色与权限的存储建议**: + + - 角色建议存储为`ADMIN`、`USER`等形式 + - 权限建议存储为`user:read`、`order:delete`等具体操作 + +2. **性能优化**: + + ```java + // 使用一次查询获取所有权限信息(避免N+1查询) + @Select("SELECT p.permission_code FROM ... WHERE ur.user_id = #{userId}") + List selectAllUserPermissions(@Param("userId") Long userId); + ``` + +3. **Spring Security的默认行为**: + + - 如果同时配置`roles()`和`authorities()`,后者会覆盖前者 + - 推荐统一使用`authorities()`方法处理所有授权信息 + +4. **最佳实践示例**: + +```java +List authorities = new ArrayList<>(); +// 添加角色(手动添加ROLE_前缀) +roles.forEach(role -> + authorities.add(new SimpleGrantedAuthority("ROLE_" + role))); +// 添加权限 +authorities.addAll(permissions.stream() + .map(SimpleGrantedAuthority::new) + .toList()); + +return User.builder() + // ... + .authorities(authorities) + .build(); +``` + +#### 5. 完整流程示意图 + +```mermaid +graph TD + A[登录请求] --> B[调用UserDetailsService] + B --> C[查询用户基本信息] + C --> D[查询用户角色] + C --> E[查询用户权限] + D --> F[构建UserDetails对象] + E --> F + F --> G[返回认证结果] +``` diff --git a/spring-security/images/image-20250714202213150.png b/spring-security/images/image-20250714202213150.png new file mode 100644 index 0000000000000000000000000000000000000000..3b2c173a03ec8205fcf79136d27b8af107b229c5 GIT binary patch literal 40446 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 literal 0 HcmV?d00001 diff --git a/spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java b/spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java index 8914ea6..bdb7a0f 100644 --- a/spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java +++ b/spring-security/step-2/src/main/java/com/spring/step2/security/service/DbUserDetailService.java @@ -43,7 +43,7 @@ public class DbUserDetailService implements UserDetailsService { String[] authorities = permissionsByUserId.toArray(String[]::new); // 也可以转成下面的形式 - // authorities = permissionsByUserId.stream() + // List authorities = permissionsByUserId.stream() // .map(SimpleGrantedAuthority::new) // .toList();