Как внедрить ResourceInfo в ContainerRequestFilter в CXF - PullRequest
0 голосов
/ 25 августа 2018

Я пытаюсь создать систему аутентификации и авторизации на основе токенов, используя Apache CXF и Spring.Я полностью слежу за этим фантастическим постом за это.Но я застрял в проблеме с моим AuthorizationFilter в самом начале.Я видел много постов, apache JIRA, комментарии github по этому поводу, но пока не смог найти обходного пути в этой, казалось бы, проблеме CXF.

@PreMatching
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
private ResourceInfo resourceInfo;

@Context
public void setResourceInfo(ResourceInfo resourceInfo) {
    this.resourceInfo = resourceInfo;
}

@Override
public void filter(final ContainerRequestContext requestContext) throws IOException {

    Method method = resourceInfo.getResourceMethod();

В приведенном выше коде внедренный resourceInfo представляет собой прокси-объект , и у него нет ни одного из связанных свойств.Итак, все, что из этого resourceInfo объекта возвращает null, более конкретно resourceInfo.getResourceMethod() - это null, что приводит к NPE.Это сообщение JIRA , относящееся к этой самой проблеме, в котором говорится:

В некоторых случаях (например, с использованием аннотации @ApplicationScoped) среда выполнения CDI создаст прокси-класс дляконкретный боб.В результате сторона CXF собирается связать метаданные конкретного поставщика с этим экземпляром прокси.Это выглядит логичным и однозначным.

Однако, интересные вещи происходят, когда CXF попытается внедрить контекстные прокси (аннотации @Context) в экземпляр провайдера.Инъекции успешны, но целевым объектом для них будет экземпляр прокси (а не реальный экземпляр за ним).Следовательно, во время выполнения, когда прокси-сервер делегирует вызов вспомогательному экземпляру, все контекстные прокси там нулевые (проще говоря, не установлены).

Ссылаясь на недавние обсуждения с Сергеем Берёзкиным, лучшим решением будетбыть делегировать аннотацию @Context в инфраструктуру CDI (как таковую, освобождая CXF от выполнения инъекций).Это предложение может нуждаться в поддержке со стороны спецификации JAX-RS.

Более простое (временное?) Возможное решение состояло бы в том, чтобы дополнить внедрение CDI внедрением @Context (делегирование этой работы CXF, как это работает прямо сейчас).для компонентов без прокси и развертываний без CDI).Это можно сделать, наблюдая за событиями ProcessInjectionTarget и предоставляя наш собственный InjectionTarget (для этого подхода есть рабочий PoC).

Что касается внедрения конструктора, похоже, что CXF не поддерживает передачу аргументов конструктору провайдера (в случае CDI, без аннотации @Context), поэтому я хотел бы рассмотреть еще одну (отдельную) проблему.

Может ли кто-нибудь помочь мне указать, в чем заключается этот простой подход:

Более простое (временное?) Возможное решение состояло бы в том, чтобы дополнить внедрение CDI внедрением @Context (делегирование этой работы CXF, как это работает сейчас для развертываний без прокси-компонентов и развертываний без CDI).Это можно сделать, наблюдая за событиями ProcessInjectionTarget и предоставляя наш собственный InjectionTarget (с рабочим PoC для этого подхода)

Или есть ли другой способ, где Spring Framework может правильно внедрить объект ResourceInfo?

Я зарегистрировал такие фильтры в моем applicationContext.xml:

<jaxrs:server id="endpoints">
    <jaxrs:providers>
            <ref bean="authenticationFilter" />
            <ref bean="authorizationFilter" />
        </jaxrs:providers>
    </jaxrs:server>

1 Ответ

0 голосов
/ 26 августа 2018

Проблема заключается в аннотации @PreMatching.

Глобальная аннотация привязки, которая может применяться к фильтру запроса контейнера, чтобы указать, что такой фильтр должен применяться глобально ко всемресурсы в приложении до фактического сопоставления ресурсов .

Ключ выделяется частью "до того, как происходит фактическое сопоставление ресурсов" .Таким образом, даже до того, как ресурс сопоставлен с запросом, фильтр вызывается.И если нет подходящего ресурса, то невозможно получить какую-либо информацию из ResourceInfo.Если вы просто удалите аннотацию @PreMatching, тогда фильтр будет называться после того, как найден соответствующий ресурс, и вы сможете получить доступ ко всей информации из ResourceInfo.

...