2017-02-14 4 views
1

Это не было проблемой в Grails 2 и теперь появляется только в Grails 3. Любой контроллер, который вызывает асинхронную задачу, не может получить доступ к SecurityContextHolder, чтобы получить вошедшей в систему во время визуализации представления ....В Grails 3.2.6 действия контроллера Async теряют доступ к 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 (или что-то подобное) и устанавливает springsecurity.sch.strategyName = "MODE_INHERITABLETHREADLOCAL" безрезультатно.

Вот несколько скриншотов показывает отладчик:

1) Эта линия в DispatcherServlet еще не выполнена. Смотрите заявление в нижней части изображение показывает .getAuthentication = NULL возвращает истинное

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. Корневая проблема заключается в том, что plugin registers an application filter без DispatcherType.ASYNC. Если вы посмотрите на документацию 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 
    } 
} 
Смежные вопросы