P
P
P_Alexander2020-04-14 23:20:48
Java
P_Alexander, 2020-04-14 23:20:48

Why doesn't accessDaniedHandler work in Spring Security?

Hello everyone, such a situation, I want to set up security in spring so that when someone climbs onto non-existent pages or closed pages, redirects to the page - access is closed. But the fact is that when I try to make a request to some left path, I am redirected to the login page, as if I entered the wrong data during authentication! I added a page to the settings in the case of "access is denied" I also added a Hadler, but the logs do not work in it, that is, it does not work ... Why is that?
Maybe I don't understand how it should work? I understand this in such a way that when entering a left or forbidden path, that is, where the user does not have rights, I should be redirected to the error page, but for some reason it redirects to the login page ...
little update:
accessDeniedHandler only fires if I'm logged in and trying to access an existing denied page. Why doesn't it work if I'm logged out and trying to access an existing forbidden page and redirects to the login page?

Spring Security Settings

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public AuthenticationSuccessHandler myAuthenticationSuccessHandler() {
        return new MyAuthenticationSuccessHandler();
    }

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

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

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider () {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService());
        authenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
        return authenticationProvider;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder amb) throws Exception {
        amb.authenticationProvider(daoAuthenticationProvider());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
//        web.debug(true);
        web.ignoring()
                .antMatchers("/resources/**")
                .antMatchers("/resources/bootstrapComponent/**")
                .antMatchers("/resources/css/**")
                .antMatchers("/resources/patternViews/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers()
                .defaultsDisabled()
                .contentTypeOptions().and()
                .frameOptions().and()
                .xssProtection()
                .block(true).and()
                .contentSecurityPolicy ( "script-src 'self'").and()
                .cacheControl();
        http.authorizeRequests()
                .antMatchers("/main", "/signin", "/signUp"/*, "/error"*/).permitAll()
                .antMatchers("/home").hasAnyRole("CEO", "Manager", "User")
                .antMatchers("/control").hasAnyRole("CEO", "Manager")
                .antMatchers("/ceo").hasAnyRole("CEO")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/signin")
                .usernameParameter("username")
                .passwordParameter("password")
                .loginProcessingUrl("/signin")
//                .defaultSuccessUrl("/processSignIn")
//                .successForwardUrl("/processSignIn")
                .successHandler(myAuthenticationSuccessHandler())
                .and()
                .logout()
                .logoutUrl("/signout")
                .logoutSuccessUrl("/signin")
                .and()
//                    .exceptionHandling().accessDeniedPage("/error");
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler());
    }
}

Handler
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    private final Logger logger = LogManager.getLogger(MyAccessDeniedHandler.class);

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        logger.debug("DEBUG from MyAccessDeniedHandler --> " + e.getMessage());
        httpServletResponse.sendRedirect( httpServletRequest.getContextPath() + "/error");
    }
}

What do I need to add or how to solve this!?
Thanks!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
O
Orkhan, 2020-04-15
@P_Alexander

accessDeniedHandler only fires if I'm logged in and trying to access an existing denied page. Why doesn't it work if I'm logged out and trying to access an existing forbidden page and redirects to the login page?

You have answered your own question. Going through the chain, it first stumbles upon an authorization problem and throws an Access Denied Exception.
Those. first it checks antMatchers and sees that the requested URl is not specified in permitAll(), going further down the chain it stumbles upon .anyRequest().authenticated()and throws an Access Denied Exception.
Besides at you the line is /errorcommented out. It is possible that it is trying to show an error, but since this page is not available being unauthorized, it first redirects to the authorization page...
Try uncommenting this line and see if it works.
If not, then try creating a controller like this:
@Controller
public class HttpErrorController implements ErrorController {

    private final MessageSource messageSource;

    @Autowired
    public HttpErrorController(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @RequestMapping("/error")
    public String handleError(
            Locale locale,
            Model model,
            HttpServletRequest request,
            Exception ex
    ) {

        Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

        if (status != null) {

            int statusCode = Integer.valueOf(status.toString());

            Map<String, String> metaData = new HashMap<>();

            // 403
            if (statusCode == HttpStatus.FORBIDDEN.value()) {

                //do somthing
            }

            // 404
            else if (statusCode == HttpStatus.NOT_FOUND.value()) {
                //do somthing
            }

            // 405
            else if (statusCode == HttpStatus.NOT_FOUND.value()) {
                //do somthing
            }

            // 500
            else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
                //do somthing
            }

        }


        return "errors/httperrors";
    }

    @Override
    public String getErrorPath() {
        return "/error";
    }

}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question