假设我们有一个带注释的休息控制器方法:
@PreAuthorize("hasPermission(#username, 'USER_PROFILE', 'WRITE')")
在Spring MVC中,我们将实现PermissionEvaluator
来实现隐藏在以下方法签名背后的授权
boolean hasPermission(
Authentication authentication,
Serializable targetId,
String targetType,
Object permission
)
只要你不需要在hasPermission方法中调用一个被动服务/方法,这似乎仍然可以使用Spring WebFlux,我想很少这样,因为你通常喜欢使用被动接口您的数据库层也是如此。如果您在此方法中调用被动服务,则需要在某个时间点block()
调用Mono
,从而因为从被动管道中调用而遇到麻烦。
在Josh Long关于Spring WebFlux安全性的教程中,他解释了如何使用路径匹配器直接在SecurityWebFilterchain
上通过提供自定义ReactiveAuthorizationManager
来实现授权。但是没有解释如何在Spring WebFlux中使用PreAuthorize
注释。
我原本希望实施一些ReactivePermissionEvaluator
Mono<Boolean> hasPermission(
Authentication authentication,
Serializable targetId,
String targetType,
Object permission
)
允许在实现中使用被动服务但我无法找到任何可以扫描ReactiveAuthorizationManager
注释的PreAuthorize
实现并将evalutation分配给被动{ {1}} PermissionEvaluator
接口也不存在。
所以最后问题是,如何实现允许调用被动服务的被动ReactivePermissionEvaluator
,例如查询数据库中的autorization信息而不阻塞?
答案 0 :(得分:0)
遗憾的是,https://github.com/spring-projects/spring-security/issues/5046的Spring Security尚不支持此功能
答案 1 :(得分:0)
这是你应该怎么做。只需从 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;
}
};
}