You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello, we are migrating to Spring Boot 3 and trying to replace deprecated GlobalMethodSecurityConfiguration, but it doesn't seems to have a clear, straightforward way of doing that. Could you suggest how we should proceed?
Currently we have this (Spring Boot 2.x)
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Autowired
ApplicationContext applicationContext;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
(1) var expressionHandler = new CustomMethodSecurityExpressionHandler();
expressionHandler.setApplicationContext(applicationContext);
return expressionHandler;
}
@Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
(2) return new CustomPermissionMetadataSource();
}
}
(1):
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
private AuthenticationTrustResolver trustResolver =
new AuthenticationTrustResolverImpl();
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication, MethodInvocation invocation) {
CustomMethodSecurityExpressionRoot root =
new CustomMethodSecurityExpressionRoot(authentication);
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(this.trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
root.setThis(invocation.getThis());
return root;
}
}
(2):
public class CustomPermissionMetadataSource extends AbstractFallbackMethodSecurityMetadataSource {
@Override
protected Collection findAttributes(Method method, Class<?> targetClass) {
if (!targetClass.getPackage().getName().startsWith("some.package")) {
return null;
}
List attributes = new ArrayList<>();
// if the class is annotated as @Controller or @RestController deny access to all methods
if (AnnotationUtils.findAnnotation(targetClass, Controller.class) != null
|| AnnotationUtils.findAnnotation(targetClass, RestController.class) != null) {
attributes.add(DENY_ALL_ATTRIBUTE);
}
// unless there is a class level annotation
var classLevelAnnotationPresent =
AnnotationUtils.findAnnotation(targetClass, PreAuthorize.class) != null ||
AnnotationUtils.findAnnotation(targetClass, PostAuthorize.class) != null ||
AnnotationUtils.findAnnotation(targetClass, NoAuthorization.class) != null;
if (classLevelAnnotationPresent) {
return null;
}
// or method level annotation
Annotation[] annotations = AnnotationUtils.getAnnotations(method);
if (annotations != null) {
for (Annotation a : annotations) {
if (a instanceof PreAuthorize || a instanceof PostAuthorize || a instanceof NoAuthorization) {
return null;
}
}
}
return attributes;
}
}
Migrated: (Spring Boot 3.x)
@Configuration
@EnableMethodSecurity
public class MethodSecurityConfig {
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public Advisor customAuthorize() {
var pattern = new JdkRegexpMethodPointcut();
pattern.setPattern("my.package.controller");
var rule = new CustomAuthorizationManager();
var interceptor = new AuthorizationManagerBeforeMethodInterceptor(pattern, rule);
interceptor.setOrder(AuthorizationInterceptorsOrder.PRE_AUTHORIZE.getOrder() - 1);
return interceptor;
}
}
public class CustomAuthorizationManager implements AuthorizationManager<MethodInvocation> {
@Override
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
(2) // contains logic defined in CustomPermissionMetadataSource and based on that returns new AuthorizationDecision(true/false)
}
}
@Component
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
@Override
public EvaluationContext createEvaluationContext(Supplier<Authentication> authentication, MethodInvocation mi) {
var context = (StandardEvaluationContext) super.createEvaluationContext(authentication, mi);
var root = new CustomMethodSecurityExpressionRoot(authentication.get());
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(new AuthenticationTrustResolverImpl());
root.setRoleHierarchy(getRoleHierarchy());
root.setThis(mi.getThis());
context.setRootObject(root);
return context;
}
}
What is the goal:
(2)
To deny access to classes annotated as @ Controller or @ RestController unless there is PreAuthorize, PostAuthorize or NoAuthorization annotation on class/method level. If PreAuthorize or PostAuthorize annotation is present, it is managed by our CustomMethodSecurityExpressionRoot unless it is NoAuthorization (our custom annotation, defining methods as 'authorization not needed') which grants access without further evaluation.
The part where I'm stuck:
Which is the correct way to migrate customMethodSecurityMetadataSource - they way I have mentioned above with CustomAuthorizationManager or something else?
The text was updated successfully, but these errors were encountered:
@YaniM thanks for the report. Sorry, it's quite challenging to go through a post with a lot of unformatted, pasted code, and I'm not clear yet on what you are trying to do and where you are getting stuck.
@YaniM thanks for the report. Sorry, it's quite challenging to go through a post with a lot of unformatted, pasted code, and I'm not clear yet on what you are trying to do and where you are getting stuck.
Also, please consult the migration guide and post here where the guide is unclear.
Hi, @jzheaux
Yes, sorry for the mess. Actually, I had missed something in the migration guide you have posted... Anyway I updated the ticket and pointed out the part where I'm not sure if that's the correct way. Thank you for your time!
Hello, we are migrating to Spring Boot 3 and trying to replace deprecated GlobalMethodSecurityConfiguration, but it doesn't seems to have a clear, straightforward way of doing that. Could you suggest how we should proceed?
Currently we have this (Spring Boot 2.x)
(1):
(2):
Migrated: (Spring Boot 3.x)
What is the goal:
(2)
To deny access to classes annotated as @ Controller or @ RestController unless there is PreAuthorize, PostAuthorize or NoAuthorization annotation on class/method level. If PreAuthorize or PostAuthorize annotation is present, it is managed by our CustomMethodSecurityExpressionRoot unless it is NoAuthorization (our custom annotation, defining methods as 'authorization not needed') which grants access without further evaluation.
The part where I'm stuck:
Which is the correct way to migrate customMethodSecurityMetadataSource - they way I have mentioned above with CustomAuthorizationManager or something else?
The text was updated successfully, but these errors were encountered: