grails - 在Grails 3.2.6中,异步 Controller 操作将失去对SecurityContextHolder的访问权限

标签 grails asynchronous grails-3.0 grails3

在Grails 2中这不是问题,仅在Grails 3中才出现。在调用 View 时,任何调用异步任务的 Controller 都无法访问SecurityContextHolder以获取登录的用户信息。

似乎在SecurityContextPersistenceFilter中,在DispatcherServlet.processDispatchResult能够呈现之前,将调用SecurityContextHolder.clearContext(),从而使呈现代码无法访问存储在SecurityContextHolder中的登录用户信息:

    try {
        SecurityContextHolder.setContext(contextBeforeChainExecution);

        chain.doFilter(holder.getRequest(), holder.getResponse());

    }
    finally {
        SecurityContext contextAfterChainExecution = SecurityContextHolder
                .getContext();
        // Crucial removal of SecurityContextHolder contents - do this before anything
        // else.
        SecurityContextHolder.clearContext();
        repo.saveContext(contextAfterChainExecution, holder.getRequest(),
                holder.getResponse());
        request.removeAttribute(FILTER_APPLIED);

        if (debug) {
            logger.debug("SecurityContextHolder now cleared, as request processing completed");
        }
    }

起初,我认为该问题与安全上下文未传递到Promise的可运行文件(或类似的东西)有关,并将springsecurity.sch.strategyName =“MODE_INHERITABLETHREADLOCAL”设置为无效。

这是显示调试器的一些屏幕截图:

1)DispatcherServlet中的这一行尚未执行。图片底部的监视语句显示.getAuthentication!= null返回true

Pre-handle execution

2)在SecurityContextPersistenceFilter中清除SecurityContextHolder之前:
Pre-security context clearing

3)从ha.handle返回后,.getAuthentication()现在为null
SecurityContextHolder is now null

4)在呈现 View /结果之前,getAuthentication()现在为null
enter image description here

为了明确起见,我试图从自定义标签库中访问springSecurityService.currentUser,该自定义标签库在布局中呈现页面的标题。

因此,在layout.gsp类型文件中:
<header id="header" class="md-whiteframe-1dp">
<g:renderHeader/></header>

具有以下renderHeader定义:
def renderHeader = { attrs, body ->

    SecUser currentUser = (SecUser) accountService.activeUser

    log.info("About to render header, session.id=" + session.id +
            (currentUser?.userLogLabel ?: " user=not_logged_in"))

    out << render(template: "/header", model: [currentUser : currentUser])
}

最佳答案

我遇到了同样的问题,并设法对其进行跟踪。我假设您正在使用spring security core plugin。根本问题是没有DispatcherType.ASYNC的plugin registers an application filter。如果您查看Spring文档spring security supports async。为了修复它,我创建了这个BeanPostProcessor并将其放在我的应用程序上下文中。

class SpringSecurityAsyncConfigurer implements BeanPostProcessor {
    @Override
    Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
        if (bean in FilterRegistrationBean && "springSecurityFilterChainRegistrationBean".equals(beanName)) {
            //for some unknown reason the plugin only has this run for request and error, adding async as the spring documentation
            //says this is supported
            bean.setDispatcherTypes(EnumSet.<DispatcherType>of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC))
        }
        bean
    }

    @Override
    Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        return bean
    }
}

关于grails - 在Grails 3.2.6中,异步 Controller 操作将失去对SecurityContextHolder的访问权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42237922/

相关文章:

javascript - nodejs强制同步调用存储json

grails - 结合@TestFor和@Integration注释grails 3

grails - 如何在项目根目录下测试GrailsPlugin类

spring - Grails,将文件上传大小限制为几兆字节

node.js - 如何复用异步回调函数?

grails - Grails 3.0应用程序在意外路径上启动。怎么修?

spring - Grails:OR 角色的@Secured 注释

grails - 是什么让敏捷比 shiro 更好?

hibernate - HQL:从日期减去天数以获取新日期

c++ - 时序图 : Thread processing over messages in queue