Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how to custom MethodSecurityMetadataSource #12345

Open
quaff opened this issue Dec 6, 2022 · 6 comments
Open

Document how to custom MethodSecurityMetadataSource #12345

quaff opened this issue Dec 6, 2022 · 6 comments
Assignees
Labels
status: feedback-provided Feedback has been provided type: enhancement A general enhancement

Comments

@quaff
Copy link
Contributor

quaff commented Dec 6, 2022

import java.lang.reflect.Method;
import java.util.Collection;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.annotation.SecuredAnnotationSecurityMetadataSource;
import org.springframework.security.access.method.MethodSecurityMetadataSource;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.util.CollectionUtils;

@Configuration(proxyBeanMethods = false)
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

	@Override
	protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
		// override @EnableGlobalMethodSecurity(securedEnabled=true)
		return new SecuredAnnotationSecurityMetadataSource() {

			@Override
			public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
				Collection<ConfigAttribute> attr = super.getAttributes(method, targetClass);
				if (CollectionUtils.isEmpty(attr)) {
					attr = findAttributes(targetClass);
				}
				return attr;
			}

		};
	}

}

GlobalMethodSecurityConfiguration is deprecated since 5.8.0 as

 * @deprecated Use {@link PrePostMethodSecurityConfiguration},
 * {@link SecuredMethodSecurityConfiguration}, or
 * {@link Jsr250MethodSecurityConfiguration} instead

please elaborate how to custom MethodSecurityMetadataSource.

@quaff quaff added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Dec 6, 2022
@jzheaux
Copy link
Contributor

jzheaux commented Dec 8, 2022

Hi, @quaff, thanks for reaching out.

What is your custom code trying to do? It appears similar in concept to what SecuredAuthorizationManager is doing, which is wired by doing @EnableMethodSecurity(securedEnabled = true):

@jzheaux jzheaux added status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged labels Dec 8, 2022
@jzheaux jzheaux self-assigned this Dec 8, 2022
@quaff
Copy link
Contributor Author

quaff commented Dec 9, 2022

@jzheaux It is a workaround of #10230

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 9, 2022
@jzheaux
Copy link
Contributor

jzheaux commented Dec 21, 2022

Thanks, @quaff.

AuthorizationManager does not have a separate API for customizing the source of security metadata. Instead, consider replacing your custom MethodSecurityMetadataSource with a custom AuthorizationManager.

In the meantime, you can achieve it by calling your MethodSecurityMetadataSource implementation like so:

public class MyAuthorizationManager implements AuthorizationManager<MethodInvocation> {
    private final MethodSecurityMetadataSource metadata = // ... custom

    @Override 
    public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
        Collection<String> attributes = toStringList(this.metadata.getAttributes(mi));
        Collection<String> authorities = toStringList(authentication.get().getAuthorities());
        return new AuthorizationDecision(!Collections.disjoint(attributes, authorities));
    }
}

And then publishing the corresponding method interceptor. You can represent your metadata source as a pointcut in the following way:

Pointcut pointcut = new StaticMethodMatcherPointcut() {
    @Override 
    public boolean matches(Method method, Class<?> targetClass) {
        return !CollectionUtils.isEmpty(this.metadata.getAttributes(m, targetClass));
    } 
};

This process is indirectly documented in the migration guide however, I think that you are right that the documentation should speak directly to custom SecurityMetadataSource implementations.

@quaff
Copy link
Contributor Author

quaff commented Jan 5, 2023

  1. MethodSecurityMetadataSource is deprecated also.
  2. this way is not intuitive as previous.

@jzheaux Could you consider provide a separate API in next release?

@jzheaux
Copy link
Contributor

jzheaux commented Jan 10, 2023

  1. MethodSecurityMetadataSource is deprecated also.

Correct, the point of the above snippet was to suggest how you could adapt your existing code. Certainly, you can write an AuthenticationManager from that looks up the values itself instead of delegating to your existing component.

  1. this way is not intuitive as previous.

What parts are less intuitive? I want to make sure we are simplifying the right thing.

Could you consider provide a separate API in next release?

It's worth considering, sure. I'm inclined to see what patterns emerge first before adding more abstractions.

@quaff
Copy link
Contributor Author

quaff commented Jan 11, 2023

What parts are less intuitive? I want to make sure we are simplifying the right thing.

Overriding method customMethodSecurityMetadataSource is more intuitive.

It's worth considering, sure. I'm inclined to see what patterns emerge first before adding more abstractions.

Thanks for your considering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: feedback-provided Feedback has been provided type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants