0

Я запускаю приложение Grails с использованием Spring Security Core Plugin.Как заставить Grails Spring Security Core отображать другую страницу в зависимости от причины отказа в доступе

Когда пользователь уже вошел в систему, пытается получить доступ к странице без доступа к ней, всегда вызывается то же действие, что и 403 в UrlMappings.groovy.

Я изо всех сил пытался сделать свою заявку на другую страницу в зависимости от причины отказа в доступе. Например: Если требуется IS_AUTHENTICATED_FULLY, я хочу перенаправить пользователя в форму, где он может повторно аутентифицироваться. Если требуется определенная роль, но нет, я хочу перенаправить пользователя на страницу, где он может запросить эту роль. И так далее ...

Кто-нибудь знает, как это сделать?

============================== ОБНОВЛЕНИЕ ================ ===================

Я попытался решить проблему с помощью обратного вызова onAuthorizationEven‌​t, описанного на docs. К сожалению, параметр события всегда идентичен независимо от правила, которое вызвало его.

По крайней мере, у меня есть доступ к URI, от которого было отказано в доступе. Есть ли способ получить правила безопасности из URI, чтобы я мог сравнить роли и статус текущего пользователя и узнать, чего не хватает? Возможно, это решит проблему.

ответ

1

После долгих исследований через Интернет, наконец, получил его на работу с некоторыми идеями от ответа @yariash «s и this post:

import org.springframework.context.ApplicationListener; 
import org.springframework.security.access.event.AuthorizationFailureEvent 
import org.springframework.security.authentication.RememberMeAuthenticationToken; 

class AuthorizationFailureEventListener 
     implements ApplicationListener<AuthorizationFailureEvent> { 

    @Override 
    public void onApplicationEvent(AuthorizationFailureEvent e) { 
     def attributes = e.getConfigAttributes() 

     if(!attributes) { 
      return 
     } 

     def authentication = e.getAuthentication() 
     def requiredAuthorities = attributes?.collect { it.getAttribute() } 
     def userAuthorities = authentication.getAuthorities().collect { it.getAuthority() } 
     def missingAuthorities = requiredAuthorities - userAuthorities 

     if(requiredAuthorities.contains('IS_AUTHENTICATED_FULLY') && 
       !(authentication instanceof RememberMeAuthenticationToken)) { 
      requiredAuthorities.remove('IS_AUTHENTICATED_FULLY') 
     } 

     e.getSource().getRequest().setAttribute("MISSING_AUTHORITIES", missingAuthorities); 
    } 

} 

Затем включите этот listenner как боб:

beans = { 
    //... 
    authorizationFailureEventListener(AuthorizationFailureEventListener) { bean -> 
     bean.autowire = "byName" 
    } 
    //... 
} 

Наконец в моем контроллере ошибок:

static mappings = { 
    //.... 
    "403"(controller:'error', action:'error403') 
    //...... 
} 

class ErrorController { 
    def error403() { 
     def missingAuthorities = request.getAttribute("MISSING_AUTHORITIES") 
     // Render the right view based on the missing authorities 
    } 
} 
+0

Хорошая работа. Вы можете принять собственный ответ. –

+0

Спасибо. Просто сделал это;) – ylima

1

Может быть, создать контроллер и получить доступ к исключению?

static mappings = { 
    //.... 
    "403"(controller:'error', action:'error403') 
    //...... 
} 


class ErrorController { 
    def error403() { 
     def message = request.exception?.cause?.message; //access message and render right view 
    } 
} 
+0

Эй, спасибо за быстрый ответ. Пробовал. К сожалению, исключение всегда равно нулю. У меня есть доступ к «AccessDeniedException», созданный Spring Security в обратном вызове 'onAuthorizationEvent'. Но он идентичен независимо от правила, которое вызвало его. Я отредактирую свой вопрос с более подробной информацией. – ylima

Смежные вопросы