Don Rhummy
Don Rhummy

Reputation: 25830

Get error stating that "methodSecurityInterceptor" is already defined when extend GlobalMethodSecurityConfiguration in SPring Boot 2.1.1

I'm overriding the GlobalMethodSecurityConfiguration class but only one method: protected MethodSecurityExpressionHandler createExpressionHandler().

When I try to run the app, I get:

Description:

The bean 'methodSecurityInterceptor', defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/testing/config/MyMethodSecurityConfig.class] and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

CONFIG CLASS

Why is it doing this when I am not overriding that base method? How can i override the MethodSecurityExpressionHandler without getting this error?

import com.testing.AadMethodSecurityExpressionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MyMethodSecurityConfig extends GlobalMethodSecurityConfiguration
{
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler()
    {
        return new MyMethodSecurityExpressionHandler();
    }
}

Expression Handler

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication;

public class MyMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler
{
    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation)
    {
        MyMethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot( authentication );
        root.setPermissionEvaluator( getPermissionEvaluator() );
        root.setTrustResolver( getTrustResolver() );
        root.setRoleHierarchy( getRoleHierarchy() );

        return root;
    }
}

Expression Root

import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication;

public class MyMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations
{
    private Object filterObject;
    private Object returnObject;
    private Object target;

    public MyMethodSecurityExpressionRoot(Authentication a)
    {
        super( a );
    }

    @Override
    public void setDefaultRolePrefix(String defaultRolePrefix)
    {
        //Simple test to see if this works
        super.setDefaultRolePrefix( "" );
    }

    public void setFilterObject(Object filterObject)
    {
        this.filterObject = filterObject;
    }

    public Object getFilterObject()
    {
        return filterObject;
    }

    public void setReturnObject(Object returnObject)
    {
        this.returnObject = returnObject;
    }

    public Object getReturnObject()
    {
        return returnObject;
    }

    void setThis(Object target)
    {
        this.target = target;
    }

    public Object getThis()
    {
        return target;
    }
}

Upvotes: 13

Views: 7554

Answers (3)

Samuel Olufemi
Samuel Olufemi

Reputation: 905

The solution below worked for me.

Set this key and values in your application.yml or application.properties

application.yml spring:
main: allow-bean-definition-overriding: true

application.properties

spring.main.allow-bean-definition-overriding=true

Upvotes: -1

Gabriel
Gabriel

Reputation: 21

I solved by merging both configuration classes

@EnableWebSecurity
public class SecurityConfig {

    @Configuration
    @RequiredArgsConstructor
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
    public static class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
        
        private final ApplicationContext applicationContext;

        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
            var expressionHandler = new CustomMethodSecurityExpressionHandler();
            expressionHandler.setApplicationContext(applicationContext);

            return expressionHandler;
        }
    }

    @Configuration
    public static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //http config
        }

    }
}

As suggested here in Spring docs

Upvotes: 1

Bruce Ritchie
Bruce Ritchie

Reputation: 1035

For anyone hitting this issue for me the solution was to remove the duplicate @EnableGlobalMethodSecurity annotation I had configured on a WebSecurityConfigurer I had setup.

Upvotes: 48

Related Questions