2017-02-14 69 views
1

在Grails 2中这不是问题,而且现在只出现在Grails 3中。任何调用异步任务的控制器都无法访问SecurityContextHolder以获取登录的用户信息,同时呈现视图....在Grails 3.2.6中,异步控制器操作失去对SecurityContextHolder的访问

看起来,在SecurityContextPersistenceFilter中,SecurityContextHolder.clearContext()被调用之前DispatcherServlet.processDispatchResult能够呈现,使渲染代码无法访问登录存储在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"); 
     } 
    } 

在f我首先认为这个问题与安全上下文没有被传递给Promise的runnable(或者其他某些东西)有关,并且将springsecurity.sch.strategyName =“MODE_INHERITABLETHREADLOCAL”设置为无效。

下面是表示调试器的一些截图:

1)尚未执行这条线的DispatcherServlet。关注声明在图像的底部显示.getAuthentication = NULL返回true

Pre-handle execution

2)之前SecurityContextHolder的在SecurityContextPersistenceFilter被清除出去! Pre-security context clearing

3)从ha.handle,.getAuthentication回国后()现在是空 SecurityContextHolder is now null

4)getAuthentication()现在呈现视图之前空/导致 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]) 
} 
+0

我开始觉得有东西的时候的sitemesh正在执行办和异步涉及的是的sitemesh已经失去了手柄上SecurityContextHolder中.... –

回答

0

你是在控制器或过滤器这样做(我的意思是 '过滤器' 不'拦截')?

因为我可以在自定义TokenFilter中毫无问题地使用它。

这就是为什么我认为大量的移动通信业务逻辑程,高者可达过滤器和处理器拦截和阻止它绑注释和东西。他们反复不断地遇到这些问题。

其实我刚刚发布的Grails对API的一个更快的版本,需要照顾大多数的这些通信问题,昨天大学

+0

凡我注意到这个问题是我的控制器正在呈现视图,视图使用的布局具有访问SCH的自定义标记。它来自该标签(这有助于为布局呈现内容),我看到对登录用户的访问权限丢失。 –

0

我打这个同样的问题,并设法追查。我假设你正在使用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 
    } 
}