Boris Burgstaller
Boris Burgstaller

Reputation: 153

Configure two cxf jaxrs clients to use the same session (cookies)

I want to connect to a REST server with a jaxrs client using apache cxf. The server has an url to authenticate and some other urls to do the actual stuff. After the login the server creates a session and keeps the connection open for 30 min. My problem is that the client doesn't store the cookies and I always get a new (not authenticated) session on the server.

I configured the clients in my spring application context.

<jaxrs:client id="loginResource" 
    serviceClass="com.mycompany.rest.resources.LoginResource" 
    address="${fsi.application.url}">
</jaxrs:client>
<jaxrs:client id="actionResource" 
    serviceClass="com.mycompany.rest.resources.ActionResource" 
    address="${fsi.application.url}">
</jaxrs:client>

How can I configure both clients to use the same session or share the session-cookie between the clients?

Upvotes: 9

Views: 2678

Answers (2)

flavio.donze
flavio.donze

Reputation: 8100

I use the following request/response filter to pass the session-id in each request:

ClientResponseFilter >> used to extract the session-id from session-cookie

ClientRequestFilter >> pass the session-id as cookie header in each request


private class SessionIdRequestFilter implements ClientRequestFilter, ClientResponseFilter {
    /** cookie header key */
    private static final String COOKIE_KEY = "Cookie"; //$NON-NLS-1$

    /** name of the session cookie */
    private String cookieName = "JSESSIONID";

    /** holds the session id from the cookie */
    private String sessionId;

    @Override
    public void filter(ClientRequestContext request) throws IOException {
        // append session cookie to request header
        if (!request.getHeaders().containsKey(COOKIE_KEY) && sessionId != null) {
            request.getHeaders().add(COOKIE_KEY, getCookieName() + "=" + sessionId); //$NON-NLS-1$
        }
    }

    @Override
    public void filter(ClientRequestContext request, ClientResponseContext response) throws IOException {
        // find sessionId only if not already set
        if (sessionId == null) {
            Map<String, NewCookie> cookies = response.getCookies();
            if (cookies != null && !cookies.isEmpty()) {
                NewCookie cookie = cookies.get(getCookieName());
                if (cookie != null) {
                    sessionId = cookie.getValue();
                }
            }
        }
    }

    private String getCookieName() {
        return cookieName;
    }
}

To register the filter use:

RestClientBuilder.newBuilder().baseUri(apiUri).register(new SessionIdRequestFilter());

Upvotes: 0

txdev
txdev

Reputation: 267

I have been struggling with the same problem, and I just finally arrived at a solution.

1) Make the client retain cookies.

WebClient.getConfig(proxy).getRequestContext().put(
        org.apache.cxf.message.Message.MAINTAIN_SESSION, Boolean.TRUE);

Perhaps there's a way to accomplish the above via configuration vs. programmatically.

2) Copy the cookies from one client to the other.

public static void copyCookies(Object sourceProxy, Object targetProxy) {
    HTTPConduit sourceConduit = WebClient.getConfig(sourceProxy).getHttpConduit();
    HTTPConduit targetConduit = WebClient.getConfig(targetProxy).getHttpConduit();
    targetConduit.getCookies().putAll(sourceConduit.getCookies());
}

After using proxy A to authenticate, I call the above method to share its cookies with proxy B, which does the actual work.

Upvotes: 3

Related Questions