I currently use Spring Zuul with spring security to dynamically release url and routing mycoservices.

So instead of adding -

.antMatchers("/api/AgendarCotacaoWSPort/**").HasRole("NAO_CORRENTISTA ") I added in my class the function that loads the role belonging to the url with .withObjectPostProcessor to call my class that searches the database for the url.

My DynamicSecurity Class implements the FilterInvocationSecurityMetadataSource which gives me permission to add in the Collection<ConfigAttribute> the relevant url to that URL.

I am currently studying Spring Cloud Gateway with Spring WebFlux and have not found a way to do the same thing instead of adding

.pathMatchers ("/login").HasRole("TEST") for each service that I want to release effect the release so that it searches the database (Redis) and returns in the settings which is the role for that endpoint that it is trying to access.

Does anyone have any idea how I can do this in the new spring security model with webflux?

My Class SecurityConfig.java

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;



@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private DynamicSecurity dynamicSecurity;  

    @Autowired
    private UrlAccessDecisionManager accessDecisionManager;

    @Autowired
    private SessionInterceptorFilter sessionFilter;

    @Bean
    public JwtAuthenticationConfig jwtConfig() {
        return new JwtAuthenticationConfig();
    }

     private static final String[] AUTH_WHITELIST = {
                "**/v2/api-docs",
                "/swagger-resources",
                "/swagger-resources/**",
                "/swagger-ui.html",
                "/configuration/ui",
                "/configuration/security",
                "/webjars/**",
                "/brasilsegapi/**",
                "/health"
        };


        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring()
                    .antMatchers("/login")
                    .antMatchers("/loginoauthbb/**")
                    .antMatchers("/oauth/**")
                    .antMatchers("/logoff")
                    .antMatchers("/health")
                    .antMatchers("**/healthcheck")
                    .antMatchers("/alterarsenha")
                    .antMatchers("/esquecisenha")
                    .antMatchers("/criarusuario")
                    .antMatchers("/alteraremail")
                    .antMatchers("/resetsenha")
                    .antMatchers("/actuator")
                    .antMatchers("/actuator/**")
                    .antMatchers(AUTH_WHITELIST)
                    .antMatchers("/api/ConsultarInformacoesOuvidoria/**")
                    .antMatchers("/api/ValidacaoProtocoloSirWSPort/**")
                    .antMatchers("/api/AgendamentoCotacaoWSPort/**")
                    .antMatchers("/api/ConsultarDadosAgile/**")
                    .antMatchers("/api/EnviarDadosFormulario/**")
                    .antMatchers("/api/sensoriamento-mobile/login/**")
                    .antMatchers("/swagger-ui.html")
                    .antMatchers("/favicon.ico")
                    .antMatchers("/api/MobileInstitucionalWSPort/**")
                    .antMatchers("/api/DadosClienteWSPort/**")
            ;
        }



    protected void configure(final HttpSecurity http) throws Exception {

        http
                .cors().and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/").denyAll()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    public <O extends FilterSecurityInterceptor> O postProcess(
                            O fsi) {
                        fsi.setSecurityMetadataSource(dynamicSecurity);
                        fsi.setAccessDecisionManager(accessDecisionManager);
                        return fsi;
                    }
                })
                .and()
                .addFilterBefore(sessionFilter, UsernamePasswordAuthenticationFilter.class)
                .logout()
                .deleteCookies("auth_code", "JSESSIONID").invalidateHttpSession(true)
                .logoutSuccessHandler(logoutSuccessHandler())
                .and()

                .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
                .and()
                .exceptionHandling().authenticationEntryPoint(
                (req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()));

    }


    @Bean
    public LogoutSuccessHandler logoutSuccessHandler() {
        return new CustomLogoutSuccessHandler();
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }

}

My Class DynamicSecurity

import java.io.IOException;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;

@Component
public class DynamicSecurity implements FilterInvocationSecurityMetadataSource {

    @Autowired
    RoleRepository roleRepository;

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        final HttpServletRequest request = ((FilterInvocation) object).getRequest();
        final HttpServletResponse response = ((FilterInvocation) object).getResponse();

        String urlWithoutContextPath = request.getRequestURI().substring(request.getContextPath().length());

        Optional<Permissao> foundUrl = roleRepository.findByUri(urlWithoutContextPath);
        if (foundUrl.isPresent()) {
            System.out.println(
                    foundUrl.get().getRolesAllowed().stream().map(this::configAttribute).collect(Collectors.toList()));

            return foundUrl.get().getRolesAllowed().stream().map(this::configAttribute).collect(Collectors.toList());
        } else if (urlWithoutContextPath.equals("/login") || urlWithoutContextPath.equals("/alterarsenha")
                || urlWithoutContextPath.equals("/esquecisenha") || urlWithoutContextPath.equals("/health")) {

            return null;
        } else {

            try {
                response.sendError(403, "acesso negado");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        // TODO Auto-generated method stub
        return FilterInvocation.class.isAssignableFrom(clazz);
    }

    private ConfigAttribute configAttribute(Roles role) {
        return new ConfigAttribute() {
            private static final long serialVersionUID = -474661209383691172L;

            @Override
            public String getAttribute() {
                return role.getAuthority();
            }
        };
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        // TODO Auto-generated method stub
        return null;
    }
}

Comment From: bclozel

Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use the issue tracker only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.