✨ 通过编程方式授权方法
This commit is contained in:
parent
1940b29247
commit
c12807224e
|
@ -1083,8 +1083,43 @@ public class AuthTestController {
|
||||||
|
|
||||||
## 其余授权方式
|
## 其余授权方式
|
||||||
|
|
||||||
|
### 前置条件
|
||||||
|
|
||||||
|
为了做一个较为通用看起来比较规范,写了一个配置类,可以在Spring配置文件中进行配置。
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "security-path")
|
||||||
|
@Schema(name = "SecurityPathsProperties对象", description = "路径忽略和认证")
|
||||||
|
public class SecurityConfigProperties {
|
||||||
|
|
||||||
|
@Schema(name = "noAuthPaths", description = "不用认证的路径")
|
||||||
|
public List<String> noAuthPaths;
|
||||||
|
|
||||||
|
@Schema(name = "securedPaths", description = "需要认证的路径")
|
||||||
|
public List<String> securedPaths;
|
||||||
|
|
||||||
|
@Schema(name = "允许的角色或权限", description = "允许的角色或权限")
|
||||||
|
public List<String> adminAuthorities;
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
之后在配置文件中指定哪些可以放行的角色或权限。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
security-path:
|
||||||
|
# 配置放行的角色或权限
|
||||||
|
admin-authorities:
|
||||||
|
- "ADMIN"
|
||||||
|
```
|
||||||
|
|
||||||
### 通过编程方式授权方法
|
### 通过编程方式授权方法
|
||||||
|
|
||||||
|
#### 简单使用
|
||||||
|
|
||||||
如果需要对权限做出自定义的需求,将传入参数作为判断权限条件,这会很有用,比如某些参数不可以传入,或者参数做权限校验等。
|
如果需要对权限做出自定义的需求,将传入参数作为判断权限条件,这会很有用,比如某些参数不可以传入,或者参数做权限校验等。
|
||||||
|
|
||||||
首先创建一个Spring组件,包含自定义的授权逻辑:
|
首先创建一个Spring组件,包含自定义的授权逻辑:
|
||||||
|
@ -1127,45 +1162,66 @@ public Result<String> lowerUser(String name) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 进阶使用
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> 参考文档:[使用自定义的 `@Bean` 而不是对 `DefaultMethodSecurityExpressionHandler` 进行子类化](https://docs.spring.io/spring-security/reference/6.3/servlet/authorization/method-security.html#_use_a_custom_bean_instead_of_subclassing_defaultmethodsecurityexpressionhandler)
|
||||||
|
|
||||||
|
在上面可以大致了解到如何使用自定义的方式进行扩展,好处是可以简单易用。
|
||||||
|
|
||||||
|
可以对比下下面章节**【使用自定义授权管理器实现自定义权限校验】**实现哪个更符合你期望预期。
|
||||||
|
|
||||||
|
```java
|
||||||
|
@Component("auth")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuthorizationLogic {
|
||||||
|
|
||||||
|
private final SecurityConfigProperties securityConfigProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基本权限检查
|
||||||
|
*/
|
||||||
|
public boolean decide(String requiredAuthority) {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
|
if (authentication == null || !authentication.isAuthenticated()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查用户是否有指定权限或是admin
|
||||||
|
return hasAuthority(authentication, requiredAuthority) || isAdmin(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否是管理员
|
||||||
|
*/
|
||||||
|
public boolean isAdmin() {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
return authentication != null && isAdmin(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAdmin(Authentication authentication) {
|
||||||
|
return securityConfigProperties.getAdminAuthorities().stream()
|
||||||
|
.anyMatch(auth -> authentication.getAuthorities().stream()
|
||||||
|
.map(GrantedAuthority::getAuthority)
|
||||||
|
.anyMatch(ga -> ga.equals(auth)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasAuthority(Authentication authentication, String authority) {
|
||||||
|
return authentication.getAuthorities().stream()
|
||||||
|
.map(GrantedAuthority::getAuthority)
|
||||||
|
.anyMatch(auth -> auth.equals(authority));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### 使用自定义授权管理器实现自定义权限校验
|
### 使用自定义授权管理器实现自定义权限校验
|
||||||
|
|
||||||
在实际开发中对于SpringSecurity提供的两个权限校验注解`@PreAuthorize`和`@PostAuthorize`,需要对这两个进行覆盖或者改造,需要实现两个`AuthorizationManager<T>`。
|
在实际开发中对于SpringSecurity提供的两个权限校验注解`@PreAuthorize`和`@PostAuthorize`,需要对这两个进行覆盖或者改造,需要实现两个`AuthorizationManager<T>`。
|
||||||
|
|
||||||
实现完成后需要显式的在配置中禁用原先的内容。
|
实现完成后需要显式的在配置中禁用原先的内容。
|
||||||
|
|
||||||
#### 前置条件
|
|
||||||
|
|
||||||
为了做一个较为通用看起来比较规范,写了一个配置类,可以在Spring配置文件中进行配置。
|
|
||||||
|
|
||||||
```java
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@Configuration
|
|
||||||
@ConfigurationProperties(prefix = "security-path")
|
|
||||||
@Schema(name = "SecurityPathsProperties对象", description = "路径忽略和认证")
|
|
||||||
public class SecurityConfigProperties {
|
|
||||||
|
|
||||||
@Schema(name = "noAuthPaths", description = "不用认证的路径")
|
|
||||||
public List<String> noAuthPaths;
|
|
||||||
|
|
||||||
@Schema(name = "securedPaths", description = "需要认证的路径")
|
|
||||||
public List<String> securedPaths;
|
|
||||||
|
|
||||||
@Schema(name = "允许的角色或权限", description = "允许的角色或权限")
|
|
||||||
public List<String> adminAuthorities;
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
之后在配置文件中指定哪些可以放行的角色或权限。
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
security-path:
|
|
||||||
# 配置放行的角色或权限
|
|
||||||
admin-authorities:
|
|
||||||
- "ADMIN"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 1. 实现前置
|
#### 1. 实现前置
|
||||||
|
|
||||||
**方式一:正则表达式**
|
**方式一:正则表达式**
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.spring.step3.controller.test;
|
||||||
import com.spring.step3.domain.vo.result.Result;
|
import com.spring.step3.domain.vo.result.Result;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.security.PermitAll;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
@ -17,8 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
@PreAuthorize("hasAuthority('USER')")
|
@PreAuthorize("hasAuthority('USER')")
|
||||||
public class SecurityProgrammaticallyController {
|
public class SecurityProgrammaticallyController {
|
||||||
|
|
||||||
// @PreAuthorize("permitAll()")
|
@PreAuthorize("permitAll()")
|
||||||
@PermitAll
|
|
||||||
@Operation(summary = "拥有 USER 的角色可以访问", description = "当前用户拥有 USER 角色可以访问这个接口")
|
@Operation(summary = "拥有 USER 的角色可以访问", description = "当前用户拥有 USER 角色可以访问这个接口")
|
||||||
@GetMapping("upper-user")
|
@GetMapping("upper-user")
|
||||||
public Result<String> upperUser() {
|
public Result<String> upperUser() {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.spring.step3.mapper;
|
package com.spring.step3.mapper;
|
||||||
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
|
@ -1,14 +1,49 @@
|
||||||
package com.spring.step3.security.annotation;
|
package com.spring.step3.security.annotation;
|
||||||
|
|
||||||
|
import com.spring.step3.security.config.properties.SecurityConfigProperties;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component("auth")
|
@Component("auth")
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class AuthorizationLogic {
|
public class AuthorizationLogic {
|
||||||
|
|
||||||
public boolean decide(String name) {
|
private final SecurityConfigProperties securityConfigProperties;
|
||||||
// 直接使用name的实现
|
|
||||||
// System.out.println(name);
|
/**
|
||||||
return name.equalsIgnoreCase("user");
|
* 基本权限检查
|
||||||
|
*/
|
||||||
|
public boolean decide(String requiredAuthority) {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
|
if (authentication == null || !authentication.isAuthenticated()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查用户是否有指定权限或是admin
|
||||||
|
boolean baseAuthority = authentication.getAuthorities().stream()
|
||||||
|
.map(GrantedAuthority::getAuthority)
|
||||||
|
.anyMatch(auth -> auth.equals(requiredAuthority));
|
||||||
|
|
||||||
|
return baseAuthority || isAdmin(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否是管理员
|
||||||
|
*/
|
||||||
|
public boolean isAdmin() {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
return authentication != null && isAdmin(authentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAdmin(Authentication authentication) {
|
||||||
|
return securityConfigProperties.getAdminAuthorities().stream()
|
||||||
|
.anyMatch(auth -> authentication.getAuthorities().stream()
|
||||||
|
.map(GrantedAuthority::getAuthority)
|
||||||
|
.anyMatch(ga -> ga.equals(auth)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue