org.wso2.carbon.uuf.api.auth.InMemorySessionManager.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.uuf.api.auth.InMemorySessionManager.java

Source

/*
 * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.wso2.carbon.uuf.api.auth;

import com.google.common.collect.Iterables;
import org.wso2.carbon.uuf.api.config.Configuration;
import org.wso2.carbon.uuf.api.exception.SessionManagementException;
import org.wso2.carbon.uuf.api.exception.UUFRuntimeException;
import org.wso2.carbon.uuf.spi.HttpRequest;
import org.wso2.carbon.uuf.spi.HttpResponse;
import org.wso2.carbon.uuf.spi.auth.SessionManager;

import java.util.Optional;
import java.util.concurrent.TimeUnit;
import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.expiry.AccessedExpiryPolicy;
import javax.cache.expiry.Duration;

/**
 * Manages sessions in memory for a single UUF app.
 * <p>
 * This session manager uses the {@link javax.cache.Cache} for saving the state of the sessions.
 *
 * @since 1.0.0
 */
public class InMemorySessionManager implements SessionManager {

    private static final long SESSION_DEFAULT_TIMEOUT = 1200L; // 20 minutes
    private static final String COOKIE_SESSION_ID = "UUFSESSIONID";
    private static final String COOKIE_CSRF_TOKEN = "CSRFTOKEN";

    private final Cache<String, Session> cache;

    /**
     * Constructs a new InMemorySessionManager.
     *
     * @param appName       name of the UUF application (or app context)
     * @param configuration app configuration
     * @throws UUFRuntimeException if an error occurred when creating/initializing the cache
     */
    public InMemorySessionManager(String appName, Configuration configuration) {
        this.cache = createCache(appName, configuration);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Session createSession(User user, HttpRequest request, HttpResponse response)
            throws SessionManagementException {
        Session session = new Session(user);
        cache.put(session.getSessionId(), session);

        // Create cookies
        response.addCookie(COOKIE_SESSION_ID,
                session.getSessionId() + "; Path=" + request.getContextPath() + "; Secure; HTTPOnly");
        response.addCookie(COOKIE_CSRF_TOKEN,
                session.getCsrfToken() + "; Path=" + request.getContextPath() + "; Secure");
        return session;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Optional<Session> getSession(HttpRequest request, HttpResponse response)
            throws SessionManagementException {
        String sessionId = request.getCookieValue(COOKIE_SESSION_ID);
        if (sessionId == null) {
            return Optional.empty();
        }
        if (!Session.isValidSessionId(sessionId)) {
            throw new SessionManagementException("Session ID '" + sessionId + "' is invalid.");
        }
        return Optional.ofNullable(cache.get(sessionId));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean destroySession(HttpRequest request, HttpResponse response) throws SessionManagementException {
        String sessionId = request.getCookieValue(COOKIE_SESSION_ID);
        if (sessionId == null) {
            return true; // Session not available
        }
        if (!Session.isValidSessionId(sessionId)) {
            throw new SessionManagementException("Session ID '" + sessionId + "' is invalid.");
        }

        // Clear the session cookie by setting its value to an empty string, Max-Age to zero, & Expires to a past date.
        String expiredCookie = "Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Path=" + request.getContextPath()
                + "; Secure; HTTPOnly";
        response.addCookie(COOKIE_SESSION_ID, expiredCookie);
        response.addCookie(COOKIE_CSRF_TOKEN, expiredCookie);
        return cache.remove(sessionId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int getCount() {
        return Iterables.size(cache);
    }

    /**
     * Creates a cache to store the sessions of the UUF app.
     * <p>
     * If the session timeout duration is not set in the configuration or if the session timeout duration value is 0
     * then the default session timeout duration of 20 minutes will be used in the cache config.
     *
     * @param cacheName     name of the cache
     * @param configuration app configuration
     * @return carbon cache for the specified cache name
     */
    private Cache<String, Session> createCache(String cacheName, Configuration configuration) {
        // Create cache config
        MutableConfiguration<String, Session> cacheConfig = new MutableConfiguration<>();
        cacheConfig.setTypes(String.class, Session.class);
        cacheConfig.setStoreByValue(false);
        long sessionTimeout = configuration.getSessionTimeout();
        sessionTimeout = sessionTimeout == 0 ? SESSION_DEFAULT_TIMEOUT : sessionTimeout;
        Duration sessionTimeOut = new Duration(TimeUnit.SECONDS, sessionTimeout);
        cacheConfig.setExpiryPolicyFactory(AccessedExpiryPolicy.factoryOf(sessionTimeOut));

        CacheManager cacheManager = Caching.getCachingProvider().getCacheManager();
        try {
            Cache<String, Session> cache = cacheManager.getCache(cacheName, String.class, Session.class);
            if (cache == null) {
                cache = cacheManager.createCache(cacheName, cacheConfig);
            }
            return cache;
        } catch (IllegalStateException e) {
            throw new UUFRuntimeException("Cannot create cache '" + cacheName + "' for session management. "
                    + "Cache manager '" + cacheManager.getClass().getName() + "' is closed.", e);
        } catch (CacheException e) {
            throw new UUFRuntimeException("Cannot create cache '" + cacheName + "' for session management. "
                    + "An error occurred configuring the cache.", e);
        } catch (IllegalArgumentException e) {
            throw new UUFRuntimeException("Cannot create cache '" + cacheName + "' for session management. "
                    + "Invalid cache configuration.", e);
        } catch (UnsupportedOperationException e) {
            throw new UUFRuntimeException("Cannot create cache '" + cacheName + "' for session management. "
                    + "Cache configuration specifies an unsupported feature.", e);
        }
    }
}