Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use both a GlobalMethodSecurityConfiguration and a WebSecurityConfigurerAdapter in a Spring app

My application has both a GlobalMethodSecurityConfiguration and a WebSecurityConfigurerAdapter configuration classes. My implementations are given below:

My GlobalMethodSecurityConfiguration implementation:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {

    @Override
    protected AuthenticationManager authenticationManager() {
        AuthenticationManager authenticationManager = new ProviderManager();
        return authenticationManager;
    }

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(permissionEvaluator());
        return expressionHandler;
    }

    @Bean
    public ApplicationPermissionEvaluator permissionEvaluator() {
        return new ApplicationPermissionEvaluator(permissionMap());
    }

    private Map<String, Permission> permissionMap() {
        Map<String, Permission> map = new HashMap<>();
        map.put("CurriculumService:findCurriculumIsAllowed", curriculumByIdOwnerPermission());
        map.put("CurriculumService:updateCurriculumIsAllowed", curriculumOwnerPermission());

        return map;
    }

    @Bean(autowire=Autowire.BY_NAME)
    public CurriculumByIdOwnerPermission curriculumByIdOwnerPermission() {
        return new CurriculumByIdOwnerPermission();
    }

    @Bean(autowire=Autowire.BY_NAME)
    public CurriculumOwnerPermission curriculumOwnerPermission() {
        return new CurriculumOwnerPermission();
    }

}

and my WebSecurityConfigurerAdapter implementation:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //@formatter:off
        http
        //.csrf().disable()
        .exceptionHandling().authenticationEntryPoint(delegatingAuthenticationEntryPoint())
        .and().formLogin()
            .loginProcessingUrl("/signin")
            .loginPage("/signin")
            .failureUrl("/signin?login_error=t")
            .defaultSuccessUrl("/dashboard", Boolean.TRUE)
        .and().logout()
            .logoutUrl("/resources/j_spring_security_logout")
            .logoutSuccessUrl("/signin")
        .and().authorizeRequests()
            .accessDecisionManager(accessDecisionManager())
            .antMatchers("/preference/sendPasswordReset/**", "/preference/passwordReset/**", "/preference/activateEmail/**", "/preference/resendActivationEmail/**").permitAll()
            .antMatchers("/preference/**").access("hasAnyRole('ROLE_BASIC_CHILDMINDER', 'ROLE_BASIC_FAMILY')")
            .antMatchers("/dashboard").access("hasAnyRole('ROLE_BASIC_CHILDMINDER', 'ROLE_BASIC_FAMILY')")
            .antMatchers("/curriculum/**").access("hasRole('ROLE_BASIC_CHILDMINDER')")
            .antMatchers("/advertisement/**/view/**").permitAll()
            .antMatchers("/advertisement/family/**").access("hasRole('ROLE_BASIC_FAMILY')")
            .antMatchers("/advertisement/childminder/**").access("hasRole('ROLE_BASIC_CHILDMINDER')")
            .antMatchers("/resources/**", "/**").permitAll();
        //@formatter:on
        super.configure(http);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }

    @Bean
    public MemberUserDetailsService userDetailsService() {
        return new MemberUserDetailsService();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder;
    }

    @Bean
    public SessionRegistryImpl sessionRegistry() {
        SessionRegistryImpl sessionRegistry = new SessionRegistryImpl();
        return sessionRegistry;
    }

    @Bean
    public AffirmativeBased accessDecisionManager() {
        AffirmativeBased accessDecisionManager = new AffirmativeBased(accessDecisionVoters());
        return accessDecisionManager;
    }

    public List<AccessDecisionVoter> accessDecisionVoters() {
        List<AccessDecisionVoter> accessDecisionVoters = new ArrayList<>();
        accessDecisionVoters.add(roleHierarchyVoter());
        accessDecisionVoters.add(webExpressionVoter());
        return accessDecisionVoters;
    }

    @Bean
    public WebExpressionVoter webExpressionVoter() {
        WebExpressionVoter webExpressionVoter = new WebExpressionVoter();
        webExpressionVoter.setExpressionHandler(defaultWebSecurityExpressionHandler());
        return webExpressionVoter;
    }

    @Bean
    public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
        defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy());
        return defaultWebSecurityExpressionHandler;
    }

    @Bean
    public RoleHierarchyVoter roleHierarchyVoter() {
        RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy());
        return roleHierarchyVoter;
    }

    @Bean
    public RoleHierarchyImpl roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        //@formatter:off
        roleHierarchy.setHierarchy(
                "ROLE_ADMINISTRATOR > ROLE_MODERATOR\n" +
                "ROLE_MODERATOR > ROLE_SUBSCRIBED_FAMILY\n" +
                "ROLE_MODERATOR > ROLE_SUBSCRIBED_CHILDMINDER\n" +
                "ROLE_SUBSCRIBED_FAMILY > ROLE_BASIC_FAMILY\n" +
                "ROLE_SUBSCRIBED_CHILDMINDER > ROLE_BASIC_CHILDMINDER");
        //@formatter:on
        return roleHierarchy;
    }

    @Bean
    public DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint() {
        DelegatingAuthenticationEntryPoint delegatingAuthenticationEntryPoint = new DelegatingAuthenticationEntryPoint(map());
        delegatingAuthenticationEntryPoint.setDefaultEntryPoint(loginUrlAuthenticationEntryPoint());
        return delegatingAuthenticationEntryPoint;
    }

    public LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map() {
        LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = new LinkedHashMap<>();
        map.put(ajaxRequestMatcher(), ajaxAuthenticationEntryPoint());
        return map;
    }

    @Bean
    public LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint() {
        LoginUrlAuthenticationEntryPoint loginUrlAuthenticationEntryPoint = new LoginUrlAuthenticationEntryPoint("/signin");
        return loginUrlAuthenticationEntryPoint;
    }

    @Bean
    public AjaxAuthenticationEntryPoint ajaxAuthenticationEntryPoint() {
        AjaxAuthenticationEntryPoint ajaxAuthenticationEntryPoint = new AjaxAuthenticationEntryPoint();
        return ajaxAuthenticationEntryPoint;
    }

    @Bean
    public AjaxRequestMatcher ajaxRequestMatcher() {
        AjaxRequestMatcher ajaxRequestMatcher = new AjaxRequestMatcher();
        return ajaxRequestMatcher;
    }

    @Bean
    public RequestDataValueProcessor requestDataValueProcessor() {
        return new CsrfRequestDataValueProcessor();
    }
}

I am not sure how to configure the authentication manager. Is the following a correct way of proceeding?

 @Override
    protected AuthenticationManager authenticationManager() {
        AuthenticationManager authenticationManager = new ProviderManager();
        return authenticationManager;
    }

Any input welcome...

like image 389
balteo Avatar asked Mar 19 '14 15:03

balteo


People also ask

Can we have two WebSecurityConfigurerAdapter?

When using Java configuration, the way to define multiple security realms is to have multiple @Configuration classes that extend the WebSecurityConfigurerAdapter base class – each with its own security configuration. These classes can be static and placed inside the main config.

What should be used instead of WebSecurityConfigurerAdapter?

You need to declare SecurityFilterChain and WebSecurityCustomizer beans instead of overriding methods of WebSecurityConfigurerAdapter class. NOTE: If you don't want to change your current code, you should keep Spring Boot version lower than 2.7. 0 or Spring Security version older than 5.7. 1.

What is the use of WebSecurityConfigurerAdapter in Spring boot?

In Spring Boot 2, if we want our own security configuration, we can simply add a custom WebSecurityConfigurerAdapter. This will disable the default auto-configuration and enable our custom security configuration. Spring Boot 2 also uses most of Spring Security's defaults.

What does anyRequest () authenticated () do?

anyRequest(). authenticated() will restrict the access for any other endpoint other than PUBLIC_URL, and the user must be authenticated.


1 Answers

I was looking for a way to do this too. The following worked for me:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends GlobalMethodSecurityConfiguration {
    @Autowired
    protected void configureGlobal (AuthenticationManagerBuilder auth) {
        // Configure auth mgr
    }

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        // Configure expression handler
    }

    @Configuration
    public static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // Configure HTTP security
        }
    }
}
like image 182
John Velonis Avatar answered Oct 02 '22 16:10

John Velonis