@P_Alexander
First head

Почему в Spring Security не работает accessDaniedHandler?

Всем привет, такая ситуация, хочу настроить в спринг секюрити что бы когда кто то полез на несуществующие страницы или закрытые страницы, перенаправляло на страницу - доступ закрыт. Но дело в том что когда я пытаюсь сделать запрос на какой то левый путь, то меня перенаправляет на страницу логина, как будто я при аутентификации ввел неправильные данные! Я добавил в настройки страницу в случае "доступ закрыт" так же добавлял хадлер, но в нем логи не работабт, то есть он не отрабатывает... Почему так?
Может я не правильно понимаю как он должен работать?! я это понимаю так, что при вводе левого или запрещенного пути, то есть где у юзера нет прав, меня должно перебросить на страницу ошибки, но почему-то перебрасывает на стр. логина...
little update:
accessDeniedHandler срабатывает только если я зологинился и пытаюсь зайти на существующую запрещенную страницу. Почему он не срабатывает если я разлогиненый и пытаюсь зайти на существующую запрещенную страницу и перекидывает на страницу логина?

Настройки Спринг Секюрити
@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());
    }
}

Хандлер
@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");
    }
}

Что мне нужно добавить или как это решить!?
Cпасибо!
  • Вопрос задан
  • 492 просмотра
Решения вопроса 1
azerphoenix
@azerphoenix Куратор тега Java
Java Software Engineer
accessDeniedHandler срабатывает только если я зологинился и пытаюсь зайти на существующую запрещенную страницу. Почему он не срабатывает если я разлогиненый и пытаюсь зайти на существующую запрещенную страницу и перекидывает на страницу логина?


Вы сами ответили на свой же вопрос. Проходя по цепочке он сперва натыкается на проблему авторизации и выдает исключение Access Denied Exception.
Т.е. сперва он проверяет antMatchers и видит, что запрошенный URl не указан вpermitAll(), проходя дальше по цепочке он натыкается на .anyRequest().authenticated() и отдает Access Denied Exception.

К тому же у вас строка /error закомментирована. Возможно, что он пытается показать ошибку, но так как эта страница недоступна будучи неавторизованным, то сперва перекидывает на страницу авторизации...

Попробуйте расскомментировать эту строку и проверьте работает ли.
Если нет, то попробуйте создать такой контроллер:

@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";
    }

}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы