在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
2)在SecurityContextPersistenceFilter中清除SecurityContextHolder之前:
3)从ha.handle返回后,.getAuthentication()现在为null
4)在呈现 View /结果之前,getAuthentication()现在为null
为了明确起见,我试图从自定义标签库中访问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/