Spring 反应式安全 |如何实现反应式 PermissionEvaluator
Posted
技术标签:
【中文标题】Spring 反应式安全 |如何实现反应式 PermissionEvaluator【英文标题】:Spring Reactive Security | How to implement a reactive PermissionEvaluator 【发布时间】:2018-10-30 04:46:29 【问题描述】:假设我们有一个带注释的休息控制器方法:
@PreAuthorize("hasPermission(#username, 'USER_PROFILE', 'WRITE')")
在 Spring MVC 中,我们将实现 PermissionEvaluator
来实现隐藏在以下方法签名后面的授权
boolean hasPermission(
Authentication authentication,
Serializable targetId,
String targetType,
Object permission
)
这在使用 Spring WebFlux 时似乎仍然有效,只要您不需要在 hasPermission 方法中调用响应式服务/方法,我猜这种情况很少发生,因为您通常希望使用响应式接口你的数据库层也是如此。如果您无论如何都要在此方法中调用响应式服务,您将需要在某个时间在某些Mono
上调用block()
,从而遇到麻烦,因为您是从响应式管道中调用的。
在来自 Josh Long 的关于 Spring WebFlux 安全性的教程中,他解释了如何通过提供自定义 ReactiveAuthorizationManager
s 使用路径匹配器直接在 SecurityWebFilterchain
上实现授权。但是没有说明Spring WebFlux中如何使用PreAuthorize
注解。
我期待实现一些ReactivePermissionEvaluator
Mono<Boolean> hasPermission(
Authentication authentication,
Serializable targetId,
String targetType,
Object permission
)
这也将允许在实现中使用反应式服务,但我无法找到 ReactiveAuthorizationManager
的任何实现,它会扫描 PreAuthorize
注释并将评估分配给反应式 PermissionEvaluator
也没有ReactivePermissionEvaluator
接口存在。
所以最后的问题是,如何实现一个响应式PermissionEvaluator
,它允许调用响应式服务,例如不阻塞地查询数据库中的自动化信息?
【问题讨论】:
【参考方案1】:遗憾的是...https://github.com/spring-projects/spring-security/issues/5046 中的 Spring Security 尚不支持此功能
【讨论】:
【参考方案2】:您应该这样做。只需从 applicationContext 获取 DefaultMethodSecurityExpressionHandler bean 并显式替换 permissionsEvaluator。
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration
@Autowire
private ApplicationContext applicationContext;
@Bean
@DependsOn("methodSecurityExpressionHandler")
public SecurityWebFilterChain springSecurityFilterChain(
ServerHttpSecurity http)
DefaultMethodSecurityExpressionHandler defaultWebSecurityExpressionHandler = this.applicationContext.getBean(DefaultMethodSecurityExpressionHandler.class);
defaultWebSecurityExpressionHandler.setPermissionEvaluator(permissionEvaluator());
return http.csrf().disable()
.httpBasic().disable()
.formLogin().disable()
.logout().disable()
.securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
.addFilterAt(tokenAuthenticationFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
.authorizeExchange()
.anyExchange().authenticated()
.and().build();
PermissionEvaluator permissionEvaluator()
return new PermissionEvaluator()
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission)
//Custom logic to evaluate @PreAuthorize("hasPermission('123', '123')")
return false;
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission)
//Custom logic to evaluate @PreAuthorize("hasPermission('123', '123','123')")
return false;
;
【讨论】:
以上是关于Spring 反应式安全 |如何实现反应式 PermissionEvaluator的主要内容,如果未能解决你的问题,请参考以下文章