Sunday, January 27, 2013

Using Spring Security in OSGi without WAB

This is actually inspired by another post that use Apache CXF in OSGi (but I couldn't find the link now).

Apache CXF D-OSGi, you can add a propety to the OSGi service so that it will use the filter (ServletFilter)

    <osgi:service ref="searchRS" interface="...search.webservice.SearchWS">       
        <osgi:service-properties>
            <entry key="service.exported.interfaces" value="*" />
            <entry key="service.exported.configs" value="org.apache.cxf.rs" />
            <entry key="org.apache.cxf.rs.httpservice.context" value="/search" />
            <entry key="org.apache.cxf.httpservice.requirefilter" value="true" />
               <entry key="org.apache.cxf.rs.provider">
                   <array>
                       <ref bean="jsonProvider" />
                   </array>
               </entry>
        </osgi:service-properties>
    </osgi:service>

and

    <osgi:service ref="customFilterChain" interface="javax.servlet.Filter">
        <osgi:service-properties>
            <entry key="org.apache.cxf.httpservice.filter" value="true" />
            <entry key="servletNames" value="none" />
        </osgi:service-properties>
    </osgi:service>

With this, the customFilterChain will be used everytime when /search has been accessed.

To setup the filter chain,

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:osgi="http://www.eclipse.org/gemini/blueprint/schema/blueprint"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/security           
                        http://www.springframework.org/schema/security/spring-security.xsd
                        http://www.eclipse.org/gemini/blueprint/schema/blueprint
                        http://www.eclipse.org/gemini/blueprint/schema/blueprint/gemini-blueprint.xsd">

    <bean id="customSecurityFilter" class="...security.filter.CustomSecurityFilter"/>

    <bean id="requestContextFilter" class="org.springframework.web.filter.RequestContextFilter"/>
    <!-- disable url rewrite, change session key -->
    <bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
   
    <bean id="springSecurityFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter" >
        <constructor-arg ref="httpSessionSecurityContextRepository" />
        <property name="forceEagerSessionCreation" value="false" />
    </bean>
   
    <bean id="basicAuthenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter" >
        <constructor-arg ref="customAuthenticationManager" />
    </bean>
   
    <bean id="http403ForbiddenEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
    <bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
        <constructor-arg ref="http403ForbiddenEntryPoint" /> <!-- can redirect to https here -->
    </bean>
   
    <bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
        <constructor-arg ref="httpSessionSecurityContextRepository"/>
        <constructor-arg ref="sessionFixationProtectionStrategy" />
    </bean>
   
    <bean id="sessionFixationProtectionStrategy" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
        <property name="migrateSessionAttributes" value="true"/>
    </bean>

    <bean id="customFilterChain" class="org.springframework.security.web.FilterChainProxy">
        <security:filter-chain-map request-matcher="ant">
            <security:filter-chain pattern="/osgi/auth/**" filters="springSecurityFilter,requestContextFilter,basicAuthenticationFilter,sessionManagementFilter,exceptionTranslationFilter"/>
            <security:filter-chain pattern="/**" filters="springSecurityFilter,requestContextFilter,customSecurityFilter,exceptionTranslationFilter"/>
        </security:filter-chain-map>
    </bean>
   
</beans>

note that we have our own AuthenticationProvider and only /auth will perform Basic Authentication Filter.

After we've migrated to Resteasy, we're still keeping the filter chain, and instead of registering to OSGi and let Apache CXF handles it, we registered to the WebContainer directly (see my other post about Resteasy & Pax Web).

3 comments:

  1. I'm obtaining an error using your sample configuration in my application:

    Attribute 'bean' is not allowed to appear in element 'ref'.

    It is very strange. It is related with line:



    Can you provide me some help?

    Thank you!

    ReplyDelete
  2. Where is "jsonProvider" defined? I have changed the line:



    by:



    to achieve parsing the file, but anyway I need to get this bean defined.

    ReplyDelete
  3. I have noticed that my previous comments didn't have proper lines:

    I write both again without symbols:

    ref bean="jsonProvider"

    ref component-id="jsonProvider"

    ReplyDelete