如何使Grails的Spring Security Core呈现不同的页面,具体取决于访问被拒绝的原因

时间:2016-08-15 20:03:39

标签: grails spring-security grails-2.0 grails-spring-security

我正在使用Spring Security Core Plugin运行Grails应用程序。

当已登录的用户尝试访问某个页面而无法访问该页面时,始终会调用在UrlMappings.groovy中配置为403的相同操作。

我一直在努力让我的应用程序呈现不同的页面,具体取决于访问拒绝的原因。例如:如果需要IS_AUTHENTICATED_FULLY,我想将用户重定向到可以重新进行身份验证的表单。如果需要特定角色但不存在,我想将用户重定向到可以请求此角色的页面。等等...

有谁知道如何存档?

==============================更新================ ==================

我尝试通过docs中描述的onAuthorizationEven‌​t回调来解决问题。不幸的是,无论触发它的规则如何,事件参数总是相同的。

至少我可以访问那些被拒绝访问的URI。有没有办法从URI获取安全规则,以便我可以比较当前用户的角色和状态,并找出缺少的内容?这可能会解决问题。

1 个答案:

答案 0 :(得分:1)

经过长时间的互联网研究后,终于得到了@yariash的回复和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);
    }

}

然后将此监听器包含为bean:

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
    }
}