,但是,我想使用诸如
@Secured
,
@RolesAllowed
,@PermitAll
或@PreAuthorize
。
furthermore,我希望/login
和/register
路公开。
现在,我已经创建了遵循安全配置(我将其删除到最重要的部分):
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain =
http
.csrf { it.disable() }
.authorizeHttpRequests {
it
.requestMatchers(HttpMethod.POST, "/auth/register", "/auth/login")
.permitAll()
.anyRequest()
.denyAll()
}
// ... further config
.build()
您可以看到,除了上面提到的路径外,我已经访问了所有路径。
问题
我的配置问题是denyAll()
过早地取消过滤器链。也就是说,该框架根本无法评估我的控制器/方法级别注释。自动返回禁止的403
现在我想在控制器中执行以下操作:
@RestController
class TodoController(private val todoService: TodoService) {
// ONLY users with role admin
@RolesAllowed(Role.ADMIN_VALUE)
// @<Some HTTP mapping>
fun method0()
// ONLY users with roles admin and user
@RolesAllowed(Role.ADMIN_VALUE, Role.USER_VALUE)
// @<Some HTTP mapping>
fun method1()
// ANY "authn" user, independent of their "auhtz" status
@PreAuthorize("isAuthenticated()")
fun method2()
// Anyone, independent of their "authn" / "authz" status
@PermitAll
// @<Some HTTP mapping>
fun method3()
// UUUUPPPPPPSSS..... Forgot to annotate? No problem, NO ONE can call this!
// @<Some HTTP mapping>
fun method4()
}
在上面可以看到的是,注释可以对端点进行颗粒状控制。如果开发人员忘记了正确注释端点方法,则不会造成损坏,因为系统默认拒绝所有内容。
// Endpoint methods in this controller can be called by anyone, regardless of "authn" / "authz" status
@PermitAll
@RestController
class TodoController
// Endpoint methods in this controller can ONLY be called by admins
@RolesAllowed(Role.ADMIN_VALUE)
@RestController
class TodoController
// Endpoint methods in this controller can ONLY be called admins and regular users
@RolesAllowed(Role.ADMIN_VALUE, Role.USER_VALUE)
@RestController
class TodoController
// Endpoint methods in this controller can ONLY be called by logged-in users (regardless of their roles)
@PreAuthorize("isAuthenticated()")
@RestController
class TodoController
/*
Endpoint methods in this controller cannot be called by anyone,
because neither the controller, nor the methods have security annotations.
The default configuration of denying everything automatically kicks in.
*/
@RestController
class TodoController
示例3
您可能想象的是,如果控制器和方法都是注释的,那么我希望方法注释过度统治控制器注释:
@PreAuthorize("isAuthenticated()")
@RestController
class TodoController {
// Overrides "isAuthenticated": Now anyone can call this
@PermitAll
fun foo()
// Has inherited "isAuthenticated" from the controller
fun bar()
// Overrides "isAuthenticated": Only users with role admin can access
@Secured(Role.ADMIN_VALUE)
fun baz()
}
SecurityConfig
我面对与Java应用程序所需的相同情况。经过漫步的弹簧安全文档和代码后,我决定实施
preauthorizeauthorizationmanager
我自己的授权决定。 this CustomPreAuthorizeAuthorizationManager
仅将决定委派给了共同的Spring Security实施,如果没有决定(所谓的方法没有JSR250/PREATUTHORIZE注释)返回拒绝请求的and。
AuthorizationDecision
,然后我们需要将带有点插的方法发布到应运行此自定义的何时。下面的示例是在春季的
poreapectorinterceptor实现中启发的,该实现是针对用
@Component
public class CustomDelegatingPreAuthorizeAuthorizationManager implements AuthorizationManager<MethodInvocation> {
private static final AuthorizationDecision DENIED_DECISION = new AuthorizationDecision(false);
private final AuthorizationManager<MethodInvocation> preAuthorizeDelegate = new PreAuthorizeAuthorizationManager();
private final AuthorizationManager<MethodInvocation> jsr250Delegate = new Jsr250AuthorizationManager();
@Override
public AuthorizationDecision check(final Supplier<Authentication> authentication, final MethodInvocation object) {
return Optional.ofNullable(preAuthorizeDelegate.authorize(authentication, object))
.or(() -> Optional.ofNullable(jsr250Delegate.authorize(authentication, object)))
.filter(AuthorizationDecision.class::isInstance)
.map(AuthorizationDecision.class::cast)
.orElse(DENIED_DECISION);
}
}
注释的方法的,我替换为用AuthorizationManager
@PreAuthorize
中启用。原因是在自定义管理人中,总是返回@RequestMapping
,如果Mehtod没有注释,将是一个被拒绝的决定,这使得Spring未拨打下一个@RestController
@EnableMethodSecurity(jsr250Enabled = true)
AuthorizationDecision
允许所有请求,这将使弹簧始终在滤链中呼叫AuthorizationInterception
,并在
@Configuration
@EnableMethodSecurity
public class MethodSecurityConfig {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public Advisor preAuthorize(final CustomDelegatingPreAuthorizeAuthorizationManager manager) {
final Pointcut pointcut = Pointcuts.union(
new AnnotationMatchingPointcut(null, RequestMapping.class, true),
new AnnotationMatchingPointcut(RequestMapping.class, true)
);
final AuthorizationManagerBeforeMethodInterceptor interceptor = new AuthorizationManagerBeforeMethodInterceptor(
pointcut,
manager
);
interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder());
return interceptor;
}
}
.
中做出决定。
SecurityFilterChain
不幸的是,我认为这种方法不会涵盖您给出的所有示例,尤其是在示例3中,您在班级级别上有一个PreAuthorizedMethodInterceptor
,并且可以覆盖方法级别。正如我之前提到的那样,
CustomAuthorizationManager
将始终返回一个
@EnableWebSecurity
public class WebSecurityConfiguration {
@Bean
public SecurityFilterChain defaultSecurityFilterChain(
final HttpSecurity http
) throws Exception {
return http
.authorizeHttpRequests(authorize ->
authorize
.anyRequest().permitAll()
)
.build();
}
}
,然后在控制器级别中找到一个
@PreAuthorize
当该方法无法执行JSR250。
对于我的场景,一旦我总是使用@PermitAll
,这应该可以起作用。
CustomAuthorizationManager
我不确定这是否是正确的方法,而是对我有用的,希望可以帮助您。