Используйте пружинную безопасность с cxf на karaf - проблема с пользовательским фильтром

В настоящее время я пытаюсь использовать spring-security (аутентификация и авторизация hmac) в службе REST cxf, развернутой в виде пакета в Karaf. (karaf 2.3, cxf 2.7.6 и spring security 3.1.4) Моя проблема в том, что я всегда получаю

 org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext

всякий раз, когда я пытаюсь достичь метода. По-видимому, я не могу заставить работать цепочку фильтров Возможно, это связано с этим https://issues.apache.org/jira/browse/DOSGI-183, так как это есть в моих весенних журналах безопасности:

Checking sorted filter chain: [Root bean: class[org.springframework.security.web.context.SecurityContextPersistenceFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 200, <hmacAuthenticationFilter>, order = 800, Root bean: class [org.springframework.security.web.savedrequest.RequestCacheAwareFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1300, Root bean: class [org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1400, Root bean: class [org.springframework.security.web.access.ExceptionTranslationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1900, <org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0>, order = 2000]

Во всяком случае, вот мой код:

Сначала я получил в комплекте A authenticationFilter и authenticationProvider, соответственно расширяющие AbstractAuthenticationProcessingFilter и AbstractUserDetailsAuthenticationProvider. Фильтр предоставляется как osgi:service, как и authenticationManager, построенный вокруг провайдера.

 <security:authentication-manager alias="defaultAuthenticationManager" erase-credentials="true">
    <security:authentication-provider ref="hmacAuthProvider"/>    
</security:authentication-manager>
<osgi:service ref="hmacAuthenticationFilter" interface="com.security.auth.IHmacAuthenticationFilter"/>
<osgi:service ref="defaultAuthenticationManager" interface="org.springframework.security.authentication.AuthenticationManager"/>

Здесь находится логика аутентификации и авторизации.

Теперь сервис: простой ресурс

@Path("test")
public class PocRessource {
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("m1")
@PreAuthorize("hasRole('ROLE_M1')")
public String m1() {
    return "calling m - 1";
}

И весеннее приложениеContext

<beans  --schema goes here --
default-lazy-init="false">
<context:annotation-config />
<context:component-scan base-package="com.security.webservice"/>
<osgi:reference id="hmacAuthenticationFilter" interface="com.security.auth.IHmacAuthenticationFilter"/>
 <osgi:reference id="authenticationManager" interface="org.springframework.security.authentication.AuthenticationManager"/>

<bean id="logInbound" class="org.apache.cxf.interceptor.LoggingInInterceptor"/>
<bean id="logOutbound" class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<bean id="pocRessource" class="com.security.webservice.PocRessource"/>
<bean id="forbiddenEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<security:global-method-security pre-post-annotations="enabled"/>
<security:http disable-url-rewriting="true" entry-point-ref="forbiddenEntryPoint" use-expressions="true"
    create-session="never" authentication-manager-ref="authenticationManager">
    <security:anonymous enabled="false"/>
    <security:session-management session-fixation-protection="none"/>
    <security:custom-filter ref="hmacAuthenticationFilter" position="FORM_LOGIN_FILTER"/>
    <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>
</security:http>
<jaxrs:server id="pocsecurityWS" address="/pocs/security">
    <jaxrs:inInterceptors>
         <ref bean="logInbound"/>
     </jaxrs:inInterceptors>
     <jaxrs:outInterceptors>
        <ref bean="logOutbound"/>
     </jaxrs:outInterceptors>
    <jaxrs:serviceBeans>
      <ref bean="pocRessource"/>
    </jaxrs:serviceBeans>
</jaxrs:server>
</beans>

Пакет генерируется через maven

    <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
                            <configuration>
                <supportedProjectTypes>
                  <supportedProjectType>jar</supportedProjectType>
                  <supportedProjectType>bundle</supportedProjectType>
                  <supportedProjectType>war</supportedProjectType>
                </supportedProjectTypes>
                <instructions>
                      <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
                      <DynamicImport-Package>*</DynamicImport-Package>
                      <Web-FilterMappings>springSecurityFilterChain;url-patterns:="/*"</Web-FilterMappings> 
                  </instructions>
            </configuration>
        </plugin>

Что мне не хватает?

Спасибо !


person jlb    schedule 31.10.2013    source источник


Ответы (1)


Итак, после нескольких дней попыток заставить его работать, мне удалось сделать это, используя .... Джерси! По-видимому, способ javax.servlet.Filter не подходит для CXF. Думаю, мне придется поместить свою логику в AbstractPhaseInterceptor. Кто-нибудь может это подтвердить? попробую один реализовать

Кому интересно, вот что я сделал:

  • сначала используйте WAB (военная упаковка в pom, затем используйте плагин пакета mavne. Будьте осторожны, чтобы поместить все зависимости с «предоставленной» областью)

    org.apache.felix maven-bundle-plugin правда

            <executions>
                <execution>
                  <id>bundle-manifest</id>
                  <phase>process-classes</phase>
                  <goals>
                    <goal>manifest</goal>
                  </goals>
                </execution>
          </executions>
    
            <configuration>
                <supportedProjectTypes>
                  <supportedProjectType>jar</supportedProjectType>
                  <supportedProjectType>bundle</supportedProjectType>
                  <supportedProjectType>war</supportedProjectType>
                </supportedProjectTypes>
    
                <instructions>
                      <Bundle-SymbolicName>${project.groupId}.${project.artifactId} </Bundle-SymbolicName>
                      <Export-Package/>
                     <Import-Package>
                          javax.servlet;version="[2.5,3)",
                          javax.servlet.http;version="[2.5,3)",
                          org.springframework.core,
                          org.springframework.web.context,
                          org.springframework.web.context.request,
                          org.springframework.security.config,
                          org.springframework.osgi.config,
                          org.springframework.context.config,
                          org.springframework.osgi.web.context.support,
                          com.leguide.backoffice.poc.security.auth,
                          org.springframework.aop,
                          org.springframework.aop.framework,
                          *
                     </Import-Package>
                      <DynamicImport-Package>*</DynamicImport-Package>
                      <Bundle-ClassPath>.,WEB-INF/classes</Bundle-ClassPath>
                      <Embed-Directory>WEB-INF/lib</Embed-Directory>
                      <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
                      <Embed-Transitive>true</Embed-Transitive>
                      <Web-ContextPath>/pocsecurity/services</Web-ContextPath>
                      <Webapp-Context>/pocsecurity/services</Webapp-Context>
                      <Web-FilterMappings>springSecurityFilterChain;url-pattern:="/*"</Web-FilterMappings> 
                  </instructions>
            </configuration>
        </plugin>
    
  • добавьте web.xml, например:

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:META-INF/spring/applicationContext.xml</param-value>
    </context-param>
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
       <url-pattern>/*</url-pattern>
    </filter-mapping>
    

используйте правильный пакет в функциях xml (благодаря Автоматическая загрузка всех зависимостей Jersey OSGi Bundle ) и все!

У меня есть эти журналы в моем карафе:

2013-11-06 11:39:49,247 | DEBUG | services/pocs/m1 | WelcomeFilesFilter               | vice.internal.WelcomeFilesFilter  128 | 82 - org.ops4j.pax.web.pax-web-runtime - 1.1.14 | Path info: null
2013-11-06 11:39:49,247 | DEBUG | services/pocs/m1 | ServletHandler                   | rvlet.ServletHandler$CachedChain 1297 | 65 - org.eclipse.jetty.util - 7.6.8.v20121106 | call filter springSecurityFilterChain
 2013-11-06 11:39:49,248 | DEBUG | services/pocs/m1 | HmacAuthenticationFilter         | ctAuthenticationProcessingFilter  189 | 84 - org.springframework.web - 3.2.3.RELEASE | Request is to process authentication
2013-11-06 11:39:49,255 | DEBUG | services/pocs/m1 | FilterSecurityInterceptor        | cept.AbstractSecurityInterceptor  215 | 110 - org.springframework.security.core - 3.1.4.RELEASE | Authorization successful
2013-11-06 11:39:49,256 | DEBUG | services/pocs/m1 | SecurityContextPersistenceFilter | SecurityContextPersistenceFilter   97 | 84 - org.springframework.web - 3.2.3.RELEASE | SecurityContextHolder now cleared, as request processing completed

У меня есть проблема с причалом, возвращающим 404, но я думаю, это что-то другое.

person jlb    schedule 06.11.2013
comment
не могли бы вы предоставить детали applicationContext для вышеуказанного решения? ИЛИ, если у вас есть полный код, относящийся ко всем 3 файлам, можете ли вы отправить ссылку? - person Srikanth Hugar; 05.11.2014
comment
извините, у меня больше нет кода. Он просто не работал на karaf. Мы закончили тем, что использовали маршрут come с конечной точкой cxfrs, с маршрутом netty/jetty непосредственно перед вызовом реализации hmac. Это выглядит примерно так: from netty -> if hmac ok, затем продолжите, иначе отправьте 401. Эффективнее, чем пытаться навязать ВОЙНУ карафу - person jlb; 14.11.2014
comment
Хорошо спасибо. Я могу добиться сейчас. позже выложу решение - person Srikanth Hugar; 19.11.2014