How to detect when the user tries to access a URL without having a ROLE for that URL in Spring Security

Asked

Viewed 63 times

0

In my system the ROLES of the screen urls are dynamically loaded from the database through a ObjectPOstProcessor as you can see below:

    public void configProducao(HttpSecurity http) throws Exception {
        AffirmativeBased affirmativeBased = new AffirmativeBased(Arrays.asList(new RoleVoter(), new WebExpressionVoter()));
        http
        .csrf().disable()
           .authorizeRequests()
           .accessDecisionManager(affirmativeBased)
              .antMatchers("/backend/ui/", "/backend/ui/auth/**", "/resource/**").permitAll()
              .anyRequest().authenticated()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess (O fsi) {
                        fsi.setSecurityMetadataSource(dynamicSecurityMetadataSource);
                        return fsi;
                    }
                })
           .and()
        .formLogin()
           .loginPage("/backend/ui/")
           .permitAll()
        .and()
        .logout()
           .invalidateHttpSession(true)
           .clearAuthentication(true)
           .logoutRequestMatcher(new AntPathRequestMatcher("/backend/ui/logout/"))
           .logoutSuccessUrl("/backend/ui/")
           .permitAll();
    }

And it checks through a class that implements FilterInvocationSecurityMetadataSource

    @Component
public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    @Autowired
    private TelaRepository telaRepository;

    @Autowired
    private PerfilRepository perfilRepository;

    private static final FogasTracer tracer = new FogasTracer(DynamicSecurityMetadataSource.class);

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

        String url = request.getRequestURI();
        url = url.replace("/backend/ui", "");

        Optional<String> urlEncontrada = telaRepository.getUrlTela(url);

        tracer.info(urlEncontrada);

        if (urlEncontrada.isPresent()) {
            Set<String> rolesDaTela = perfilRepository.getPerfisQueTemAcessoTela(urlEncontrada.get());
            Collection<ConfigAttribute> attributes = new HashSet<>();

            for (String role : rolesDaTela) {
                tracer.info(role);
                attributes.add(new SecurityConfig(role));
            }

            return attributes;
        }

        return null;
        }

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

       @Override
       public boolean supports(Class<?> clazz) {
           return FilterInvocation.class.isAssignableFrom(clazz);
       }

    }

as you can see in the method getAttributes() I can already search the url and restrict by ROLE from the bank, my problem is that when a user tries to access a url without having the necessary role spring throws me to a default error page (/error), where I would like to redirect the user to a denied access page that I have already implemented. How I can verify when the user tried to access a page that he does not have access to?

2 answers

2

You can also implement Annotation @Secured methods that depend on specific roles (controllers, services...).

@Secured ({"ROLE_USER", "ROLE_ADMIN"})
public void meuMetodoSeguroPorRoles() {
   ...
}

Implementation details can be seen on documentation.

0


I managed to solve my problem in a very simple way, even in the method configProducao() I put only one exceptionHandling as you can see below:

.exceptionHandling().accessDeniedPage("/backend/ui/unauthorized")

full implementation:

public void configProducao(HttpSecurity http) throws Exception {
    AffirmativeBased affirmativeBased = new AffirmativeBased(Arrays.asList(new RoleVoter(), new WebExpressionVoter()));
    http
    .exceptionHandling().accessDeniedPage("/backend/ui/unauthorized")
    .and()
    .csrf().disable()
       .authorizeRequests()
       .accessDecisionManager(affirmativeBased)
          .antMatchers("/backend/ui/", "/backend/ui/auth/**", "/resource/**").permitAll()
          .anyRequest().authenticated()
            .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                @Override
                public <O extends FilterSecurityInterceptor> O postProcess (O fsi) {
                    fsi.setSecurityMetadataSource(dynamicSecurityMetadataSource);
                    return fsi;
                }
            })
       .and()
    .formLogin()
       .loginPage("/backend/ui/")
       .permitAll()
    .and()
    .logout()
       .invalidateHttpSession(true)
       .clearAuthentication(true)
       .logoutRequestMatcher(new AntPathRequestMatcher("/backend/ui/logout/"))
       .logoutSuccessUrl("/backend/ui/")
       .permitAll();
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.