Статьи

Общий перехватчик запросов CXF для всех пакетов OSGi

Я уже несколько месяцев работаю над Apache CXF, Karaf, Felix и считаю, что все эти технологии очень интересны для работы. Работая над некоторыми вариантами использования, я попал в ситуацию, когда мне нужен только один перехватчик, который должен выполняться при каждом HTTP-запросе, отправляемом любому из пакетов, развернутых под приложением в Karaf.

По сути, я хочу авторизовать каждый запрос, изменить некоторые заголовки и выполнить некоторые проверки безопасности, независимо от того, какой запрос был отправлен в систему, и что наиболее важно, я хочу сделать это в одном классе. Я нашел много способов добавить перехватчик в каждый пакет, но я хочу сделать это в каком-то централизованном месте / пакете, чтобы все запросы могли быть обработаны из этого пакета. Он может просто отклонить любой запрос после некоторой авторизации или передать его соответствующему пакету (cxf делает это внутренне).

При этом я узнал, что CXF всегда создает отдельную BUS для каждого RestServer, который инициализируется в Blueprint комплекта. Но для достижения моей цели мы должны зарегистрировать все пакеты на одной шине и применить перехватчик к этой шине. При этом мы можем контролировать все запросы, поступающие на шину.

Общий перехватчик

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class CommonInterceptor extends AbstractPhaseInterceptor {
 
    public CommonInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }
 
    public void handleMessage(Message message) throws Fault {
         
                /**
         * Here write whatever logic you want to implement on each HTTP call sent to your project.
         *
         * This interceptor will be called on every request that is being recieved by container and then will be sent
         * to the relevant bundle/class for handling.
         */
 
        String url = ( String ) message.get( URL_KEY_ );
        String method = ( String ) message.get( Message.HTTP_REQUEST_METHOD );
 
        LOGGER.debug( "################### Authentication Interceptor Validating Request : " + url + "####################" );
 
        Map< String, List< String >> headers = Headers.getSetProtocolHeaders( message );
                 
                if ( headers.containsKey( X_AUTH_TOKEN ) ) {
                     return;
                }else{
                     message.getInterceptorChain().abort();
                }
         
          }
}

Выше приведен общий код перехватчика, где вы можете делать что угодно с запросом, отправляемым на ваш сервер. В конструкторе я назначаю фазу, к которой будет подключен этот перехватчик. В CXF есть несколько фаз. Вы можете получить информацию о Фазах по ссылке: Фазы в CXF.

Расширение AbstractFeature:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public class InterceptorManager extends AbstractFeature {
 
    private static final String COMMON_BUS_NAME = "javapitshop_bus";
    private static final Logger LOGGER = LoggerFactory.getLogger(InterceptorManager.class);
    private static final Interceptor< Message > COMMON_INTERCEPTOR = new CommonInterceptor();
 
    protected void initializeProvider(InterceptorProvider provider, Bus bus) {
         
        if ( COMMON_BUS_NAME.equals( bus.getId() ) ) {
            LOGGER.debug( " ############## Registering Common Interceptor on BUS ##############" );
            bus.getInInterceptors().add( COMMON_INTERCEPTOR );
        } else {
            LOGGER.error( " ############## Bus Id: '" + bus.getId() + "' doesn't matched with system bus id ##############" );
        }  
    }
}

В приведенном выше коде я расширяю класс AbstractFeature и подключаю метод initilizeProvider. Тогда я дал имя нашему общему автобусу. По сути, всякий раз, когда устанавливается любой OSGi Bundle, он регистрируется на шине. В этом случае мы проверяем, имеет ли пакет желаемый идентификатор шины. Этот идентификатор шины будет уникальным для всей системы, и все пакеты, имеющие этот идентификатор шины, будут зарегистрированы на одной и той же шине, и каждый запрос, связанный с этими пакетами, будет сначала отправлен в CommonInterceptor.

Регистрация автобусов в связках:

1
2
3
4
5
<cxf:bus id="javapitshop_bus">
        <cxf:features>
            <cxf:logging />
        </cxf:features>
    </cxf:bus>

Чтобы зарегистрировать пакеты на одной и той же шине, вы должны указать идентификатор этой шины и зарегистрировать его в файле blueprint.xml пакета. Сделайте это во всех соответствующих пакетах, и всем этим пакетам будет назначена одна и та же шина, и CommonInterceptor будет автоматически внедрен во все пакеты.

  • Вы можете загрузить полный исходный код с моего Github .