How to enable session management in CXF embedded

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

How to enable session management in CXF embedded

Horste Wens
Hi,



We are currently using the CXF JAXRSServerFactoryBean (Version 2.7.14) to
dynamically create REST endpoints in an OSGI environment (Felix). The
endpoints are secured with BASIC auth using a JAAS Interceptor. Simplified
code snippet:

JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setResourceClasses(CustomerService.class);
sf.setResourceProvider(CustomerService.class, new SingletonResourceProvider(
new CustomerService()));
sf.setAddress("http://localhost:9000/");
Properties properties = System.getProperties();
properties.setProperty("java.security.auth.login.config",
"./src/main/java/demo/jaxrs/server/jaas.cfg");
List<Object> providers = *(List<Object>) sf.getProviders()*;
JAASAuthenticationFilter authenticationFilter = new
JAASAuthenticationFilter();
authenticationFilter.setContextName("BookLogin");
providers.add(authenticationFilter);
sf.setProviders(providers);
sf.create();

A new requirement is to enable session cookies for this authentication
type. Currently, each request requires a full authentication (user/pw
check). Using session cookies, we would have only one full authentication
at the beginning of a user session and afterwards the session cookie is
used instead (until invalid).

I managed to enable session management by creating a server
programmatically with a spring security filter in place. I used the
following tutorial with some modifications:
https://www.javacodegeeks.com/2014/09/embedded-jetty-and-apache-cxf-secure-rest-services-with-spring-security.html.
Code example (without the custum AppConfig+ WebSecurityConfigurerAdapter!):

Server server = new Server(8080);



ServletHolder servletHolder = new ServletHolder(new CXFServlet());

ServletContextHandler context = new ServletContextHandler();

context.setContextPath("/");

context.addServlet(servletHolder, "/rest/*");

context.addEventListener(new ContextLoaderListener());



context.setInitParameter("contextClass",
AnnotationConfigWebApplicationContext.class.getName());

context.setInitParameter("contextConfigLocation", AppConfig.class
.getName());

context.setInitParameter("org.eclipse.jetty.servlet.SessionCookie",
"MYSESSIONID");

context.setInitParameter(
"org.eclipse.jetty.servlet.SessionIdPathParameterNam", "mysessionid");



context.addFilter(new FilterHolder(new DelegatingFilterProxy(
"springSecurityFilterChain")), "/*",EnumSet.allOf(DispatcherType.class));



HashSessionManager sm = new HashSessionManager();

context.setSessionHandler(new SessionHandler(sm));



server.setHandler(context);

server.start();

Either way would be fine for us as long as we eventually have: (1) Session
Cookies enabled + (2) Dynamic asynchronous REST endpoint creation with in a
single server.

Unfortunately, I was not able to make session management + spring security
work for the JAXRSServerFactoryBean approach, nor could I find a way to
dynamically create additional endpoints using the server-based approach.

Can anyone help with this? Further hints on how to proceed with either way
are highly appreciated.

Regards,

Chris
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to enable session management in CXF embedded

andrew dwyer
 Are you using spring? These pages may assist:
http://cxf.apache.org/docs/jaxrs-services-configuration.html
http://cxf.apache.org/docs/standalone-http-transport.html

The code below should set up an embedded jetty engine with session support.
When you create your jaxrs service on the same port it should start the
engine:

JettyHTTPServerEngineFactory engineFactory = new
JettyHTTPServerEngineFactory();
JettyHTTPServerEngine jettyHTTPServerEngine =
engineFactory.createJettyHTTPServerEngine("localhost", 9000, "http");
jettyHTTPServerEngine.setSessionSupport(true);
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
...
sf.setAddress("http://localhost:9000/");
Server server = sf.create();

Cheers
Andrew
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to enable session management in CXF embedded

Horste Wens
Hi Andrew,

thanks for the very quick reply. I've just tried out the proposal.
Unfortunately, it has no effect so far. The server still won't issue
session cookies. I have already tried a similar approach:

      org.apache.cxf.endpoint.Server cxfServer = sf.create();

      JettyHTTPDestination jettyDestination = (JettyHTTPDestination)
cxfServer.getDestination();

      JettyHTTPServerEngine serverEngine = (JettyHTTPServerEngine)
jettyDestination.getEngine();

      serverEngine.setSessionSupport(true);


Using Spring Security I could make it work, but not with the ServerFactory.
There was a code snippet in my last mail for this approach. Find below the
corresponding WebSecurity config. Note that it was important to configure
the SessionCreatenPolicy as part of the configure method. I wonder if the
Jetty server can be configured directly this way.

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity( securedEnabled = true )

public class InMemorySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired

    public void configureGlobal(AuthenticationManagerBuilder auth) throws
Exception {

        auth.inMemoryAuthentication()

            .withUser("me").password("me").roles("USER").and().withUser(
"admin").password("me").roles("USER", "ADMIN");

    }

    @Override

    protected void configure( HttpSecurity http ) throws Exception {

        http.httpBasic().and()


.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS
).and()

            .authorizeRequests().antMatchers("/**").hasRole( "USER" );

    }

}


Regards,


Christof



2017-07-11 8:39 GMT+02:00 Andrew Dwyer <[hidden email]>:

>  Are you using spring? These pages may assist:
> http://cxf.apache.org/docs/jaxrs-services-configuration.html
> http://cxf.apache.org/docs/standalone-http-transport.html
>
> The code below should set up an embedded jetty engine with session support.
> When you create your jaxrs service on the same port it should start the
> engine:
>
> JettyHTTPServerEngineFactory engineFactory = new
> JettyHTTPServerEngineFactory();
> JettyHTTPServerEngine jettyHTTPServerEngine =
> engineFactory.createJettyHTTPServerEngine("localhost", 9000, "http");
> jettyHTTPServerEngine.setSessionSupport(true);
> JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
> ...
> sf.setAddress("http://localhost:9000/");
> Server server = sf.create();
>
> Cheers
> Andrew
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to enable session management in CXF embedded

andrew dwyer
I had a quick play around and I can confirm sessions are working for me.
I'm running CXF 3.1.5 in Jboss Fuse. Have you checked that the client
you're using has sessions enabled?

The code that I used is below:

== Spring config ==

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:httpj="
http://cxf.apache.org/transports/http-jetty/configuration"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://cxf.apache.org/transports/http/configuration
              http://cxf.apache.org/schemas/configuration/http-conf.xsd
        http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
        http://cxf.apache.org/transports/http-jetty/configuration
http://cxf.apache.org/schemas/configuration/http-jetty.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml" />

    <httpj:engine-factory bus="cxf" id="my-engine">
        <httpj:engine port="8686">
            <httpj:sessionSupport>true</httpj:sessionSupport>
        </httpj:engine>
    </httpj:engine-factory>

    <bean id="testBean" class="testing.Service" />

    <jaxrs:server id="cxfJaxrsServer" address="http://0.0.0.0:8686/test"
depends-on="my-engine">
        <jaxrs:providers>
            <bean
class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
        </jaxrs:providers>
        <jaxrs:serviceBeans>
            <ref bean="customerBean" />
        </jaxrs:serviceBeans>
    </jaxrs:server>

</beans>

 == Sample service ==

@Path("/service")
public class Service
{

    @Context
    private HttpServletRequest httpRequest;

    @Path("/set")
    @GET
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.TEXT_PLAIN)
    public String test()
    {
        httpRequest.getSession().setAttribute("test", "test value");
        return "bundle2";
    }

    @Path("/get")
    @GET
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.TEXT_PLAIN)
    public String test2()
    {
        return (String)httpRequest.getSession().getAttribute("test");
    }
}

== CXF dependencies ==
cxf-rt-frontend-jaxrs, cxf-rt-transports-http-jetty,
cxf-rt-rs-extension-providers

Cheers
Andrew
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to enable session management in CXF embedded

Sergey Beryozkin
Administrator
Hi

Thanks, the remaining piece of the puzzle is probably about wiring in
SpringSecurity with the embedded Jetty somehow, probably one needs to
register a CXF interceptor which will use SpringSecurity
AuthenticationManager/etc

Sergey

On 12/07/17 01:22, Andrew Dwyer wrote:

> I had a quick play around and I can confirm sessions are working for me.
> I'm running CXF 3.1.5 in Jboss Fuse. Have you checked that the client
> you're using has sessions enabled?
>
> The code that I used is below:
>
> == Spring config ==
>
> <?xml version="1.0" encoding="UTF-8"?>
> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>         xmlns:httpj="
> http://cxf.apache.org/transports/http-jetty/configuration"
>         xmlns:jaxrs="http://cxf.apache.org/jaxrs"
>         xmlns="http://www.springframework.org/schema/beans"
>         xmlns:http="http://cxf.apache.org/transports/http/configuration"
>         xsi:schemaLocation="http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans.xsd
>                    http://cxf.apache.org/transports/http/configuration
>                http://cxf.apache.org/schemas/configuration/http-conf.xsd
>          http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
>          http://cxf.apache.org/transports/http-jetty/configuration
> http://cxf.apache.org/schemas/configuration/http-jetty.xsd">
>
>      <import resource="classpath:META-INF/cxf/cxf.xml" />
>
>      <httpj:engine-factory bus="cxf" id="my-engine">
>          <httpj:engine port="8686">
>              <httpj:sessionSupport>true</httpj:sessionSupport>
>          </httpj:engine>
>      </httpj:engine-factory>
>
>      <bean id="testBean" class="testing.Service" />
>
>      <jaxrs:server id="cxfJaxrsServer" address="http://0.0.0.0:8686/test"
> depends-on="my-engine">
>          <jaxrs:providers>
>              <bean
> class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
>          </jaxrs:providers>
>          <jaxrs:serviceBeans>
>              <ref bean="customerBean" />
>          </jaxrs:serviceBeans>
>      </jaxrs:server>
>
> </beans>
>
>   == Sample service ==
>
> @Path("/service")
> public class Service
> {
>
>      @Context
>      private HttpServletRequest httpRequest;
>
>      @Path("/set")
>      @GET
>      @Consumes(MediaType.TEXT_PLAIN)
>      @Produces(MediaType.TEXT_PLAIN)
>      public String test()
>      {
>          httpRequest.getSession().setAttribute("test", "test value");
>          return "bundle2";
>      }
>
>      @Path("/get")
>      @GET
>      @Consumes(MediaType.TEXT_PLAIN)
>      @Produces(MediaType.TEXT_PLAIN)
>      public String test2()
>      {
>          return (String)httpRequest.getSession().getAttribute("test");
>      }
> }
>
> == CXF dependencies ==
> cxf-rt-frontend-jaxrs, cxf-rt-transports-http-jetty,
> cxf-rt-rs-extension-providers
>
> Cheers
> Andrew
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to enable session management in CXF embedded

Horste Wens
In reply to this post by andrew dwyer
Hi Andrew,

thanks a lot for your great support! It now works for me as well. I hoped
the JAASInterceptor would use the session to cache the login credentials,
but  this is not case. If I store them myself in the session using a custom
interceptor, then the session and the session cookie is created. I don't
even need spring security for this anymore.

The only thing missing now is a proper session timeout for the cookie.
Currently, it seems to be valid forever.

Do you have any idea how to set a timeout? The Jetty param seems to be
"org.eclipse.jetty.servlet.MaxAge", but I couldn't figure out how to
configure it in this scenario. context.setInitParameter requires the
servlet context, which I don't have.

Regards,

Chris



2017-07-12 2:22 GMT+02:00 Andrew Dwyer <[hidden email]>:

> I had a quick play around and I can confirm sessions are working for me.
> I'm running CXF 3.1.5 in Jboss Fuse. Have you checked that the client
> you're using has sessions enabled?
>
> The code that I used is below:
>
> == Spring config ==
>
> <?xml version="1.0" encoding="UTF-8"?>
> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>        xmlns:httpj="
> http://cxf.apache.org/transports/http-jetty/configuration"
>        xmlns:jaxrs="http://cxf.apache.org/jaxrs"
>        xmlns="http://www.springframework.org/schema/beans"
>        xmlns:http="http://cxf.apache.org/transports/http/configuration"
>        xsi:schemaLocation="http://www.springframework.org/schema/beans
> http://www.springframework.org/schema/beans/spring-beans.xsd
>                   http://cxf.apache.org/transports/http/configuration
>               http://cxf.apache.org/schemas/configuration/http-conf.xsd
>         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/
> jaxrs.xsd
>         http://cxf.apache.org/transports/http-jetty/configuration
> http://cxf.apache.org/schemas/configuration/http-jetty.xsd">
>
>     <import resource="classpath:META-INF/cxf/cxf.xml" />
>
>     <httpj:engine-factory bus="cxf" id="my-engine">
>         <httpj:engine port="8686">
>             <httpj:sessionSupport>true</httpj:sessionSupport>
>         </httpj:engine>
>     </httpj:engine-factory>
>
>     <bean id="testBean" class="testing.Service" />
>
>     <jaxrs:server id="cxfJaxrsServer" address="http://0.0.0.0:8686/test"
> depends-on="my-engine">
>         <jaxrs:providers>
>             <bean
> class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
>         </jaxrs:providers>
>         <jaxrs:serviceBeans>
>             <ref bean="customerBean" />
>         </jaxrs:serviceBeans>
>     </jaxrs:server>
>
> </beans>
>
>  == Sample service ==
>
> @Path("/service")
> public class Service
> {
>
>     @Context
>     private HttpServletRequest httpRequest;
>
>     @Path("/set")
>     @GET
>     @Consumes(MediaType.TEXT_PLAIN)
>     @Produces(MediaType.TEXT_PLAIN)
>     public String test()
>     {
>         httpRequest.getSession().setAttribute("test", "test value");
>         return "bundle2";
>     }
>
>     @Path("/get")
>     @GET
>     @Consumes(MediaType.TEXT_PLAIN)
>     @Produces(MediaType.TEXT_PLAIN)
>     public String test2()
>     {
>         return (String)httpRequest.getSession().getAttribute("test");
>     }
> }
>
> == CXF dependencies ==
> cxf-rt-frontend-jaxrs, cxf-rt-transports-http-jetty,
> cxf-rt-rs-extension-providers
>
> Cheers
> Andrew
>
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: How to enable session management in CXF embedded

andrew dwyer
Hi Chris,

You could call JettyHTTPServerEngine.getContextHandler to get the context
for your specific URL and then call:



context.getSessionHandler().getSessionManager().setMaxInactiveInterval(
timeout);



I haven’t tested this so I'm not sure if it would work.


Andrew



On 25 July 2017 at 00:49, Horste Wens <[hidden email]> wrote:

> Hi Andrew,
>
> thanks a lot for your great support! It now works for me as well. I hoped
> the JAASInterceptor would use the session to cache the login credentials,
> but  this is not case. If I store them myself in the session using a custom
> interceptor, then the session and the session cookie is created. I don't
> even need spring security for this anymore.
>
> The only thing missing now is a proper session timeout for the cookie.
> Currently, it seems to be valid forever.
>
> Do you have any idea how to set a timeout? The Jetty param seems to be
> "org.eclipse.jetty.servlet.MaxAge", but I couldn't figure out how to
> configure it in this scenario. context.setInitParameter requires the
> servlet context, which I don't have.
>
> Regards,
>
> Chris
>
>
>
> 2017-07-12 2:22 GMT+02:00 Andrew Dwyer <[hidden email]>:
>
> > I had a quick play around and I can confirm sessions are working for me.
> > I'm running CXF 3.1.5 in Jboss Fuse. Have you checked that the client
> > you're using has sessions enabled?
> >
> > The code that I used is below:
> >
> > == Spring config ==
> >
> > <?xml version="1.0" encoding="UTF-8"?>
> > <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> >        xmlns:httpj="
> > http://cxf.apache.org/transports/http-jetty/configuration"
> >        xmlns:jaxrs="http://cxf.apache.org/jaxrs"
> >        xmlns="http://www.springframework.org/schema/beans"
> >        xmlns:http="http://cxf.apache.org/transports/http/configuration"
> >        xsi:schemaLocation="http://www.springframework.org/schema/beans
> > http://www.springframework.org/schema/beans/spring-beans.xsd
> >                   http://cxf.apache.org/transports/http/configuration
> >               http://cxf.apache.org/schemas/configuration/http-conf.xsd
> >         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/
> > jaxrs.xsd
> >         http://cxf.apache.org/transports/http-jetty/configuration
> > http://cxf.apache.org/schemas/configuration/http-jetty.xsd">
> >
> >     <import resource="classpath:META-INF/cxf/cxf.xml" />
> >
> >     <httpj:engine-factory bus="cxf" id="my-engine">
> >         <httpj:engine port="8686">
> >             <httpj:sessionSupport>true</httpj:sessionSupport>
> >         </httpj:engine>
> >     </httpj:engine-factory>
> >
> >     <bean id="testBean" class="testing.Service" />
> >
> >     <jaxrs:server id="cxfJaxrsServer" address="http://0.0.0.0:8686/test"
> > depends-on="my-engine">
> >         <jaxrs:providers>
> >             <bean
> > class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
> >         </jaxrs:providers>
> >         <jaxrs:serviceBeans>
> >             <ref bean="customerBean" />
> >         </jaxrs:serviceBeans>
> >     </jaxrs:server>
> >
> > </beans>
> >
> >  == Sample service ==
> >
> > @Path("/service")
> > public class Service
> > {
> >
> >     @Context
> >     private HttpServletRequest httpRequest;
> >
> >     @Path("/set")
> >     @GET
> >     @Consumes(MediaType.TEXT_PLAIN)
> >     @Produces(MediaType.TEXT_PLAIN)
> >     public String test()
> >     {
> >         httpRequest.getSession().setAttribute("test", "test value");
> >         return "bundle2";
> >     }
> >
> >     @Path("/get")
> >     @GET
> >     @Consumes(MediaType.TEXT_PLAIN)
> >     @Produces(MediaType.TEXT_PLAIN)
> >     public String test2()
> >     {
> >         return (String)httpRequest.getSession().getAttribute("test");
> >     }
> > }
> >
> > == CXF dependencies ==
> > cxf-rt-frontend-jaxrs, cxf-rt-transports-http-jetty,
> > cxf-rt-rs-extension-providers
> >
> > Cheers
> > Andrew
> >
>
Loading...