com.kuprowski.redis.security.core.session.RedisSessionRegistry.java Source code

Java tutorial

Introduction

Here is the source code for com.kuprowski.redis.security.core.session.RedisSessionRegistry.java

Source

package com.kuprowski.redis.security.core.session;

import java.security.Principal;
import java.util.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.util.Assert;

/**
 * ********************************************************
 * Copyright: 2012 Tomek Kuprowski
 *
 * License: GPLv2: http://www.gnu.org/licences/gpl.html
 *
 * @author Tomek Kuprowski (tomekkuprowski at gmail dot com)
 * *******************************************************
 */
/**
 * Implementation of <code>SessionRegistry</code> which stores a <code>SessionInformation</code> in Redis
 * 
 */
public class RedisSessionRegistry extends SessionRegistryImpl implements InitializingBean {

    private RedisConnectionFactory connectionFactory;
    protected RedisTemplate<String, SessionInformation> sessionIdsTemplate = new RedisTemplate<String, SessionInformation>();
    protected RedisTemplate<String, String> principalsTemplate = new RedisTemplate<String, String>();

    @Required
    public void setConnectionFactory(RedisConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }

    @Override
    public List<Object> getAllPrincipals() {
        Set<String> all = principalsTemplate.opsForSet().members(buildPrincipalsAllKey());
        if (all == null) {
            return new ArrayList<Object>();
        }
        return new ArrayList<Object>(all);
    }

    protected Set<String> getSessionsUsedByPrincipal(Object principal) {
        return principalsTemplate.opsForSet().members(buildPrincipalKey(principal));
    }

    @Override
    public List<SessionInformation> getAllSessions(Object principal, boolean includeExpiredSessions) {
        final Set<String> sessionsUsedByPrincipal = getSessionsUsedByPrincipal(principal);

        if (sessionsUsedByPrincipal == null) {
            return Collections.emptyList();
        }

        List<SessionInformation> list = new ArrayList<SessionInformation>(sessionsUsedByPrincipal.size());

        for (String sessionId : sessionsUsedByPrincipal) {
            SessionInformation sessionInformation = getSessionInformation(sessionId);

            if (sessionInformation == null) {
                continue;
            }

            if (includeExpiredSessions || !sessionInformation.isExpired()) {
                list.add(sessionInformation);
            }
        }

        return list;
    }

    @Override
    public SessionInformation getSessionInformation(String sessionId) {
        Assert.hasText(sessionId, "SessionId required as per interface contract");
        return sessionIdsTemplate.opsForValue().get(buildSessionIdsKey(sessionId));
    }

    @Override
    public void refreshLastRequest(String sessionId) {
        Assert.hasText(sessionId, "SessionId required as per interface contract");

        SessionInformation info = getSessionInformation(sessionId);

        if (info != null) {
            info.refreshLastRequest();
            sessionIdsTemplate.opsForValue().set(buildSessionIdsKey(sessionId), info);
        }
    }

    @Override
    public void registerNewSession(String sessionId, Object principal) {
        Assert.hasText(sessionId, "SessionId required as per interface contract");
        Assert.notNull(principal, "Principal required as per interface contract");

        if (logger.isDebugEnabled()) {
            logger.debug("Registering session " + sessionId + ", for principal " + principal);
        }

        if (getSessionInformation(sessionId) != null) {
            removeSessionInformation(sessionId);
        }

        sessionIdsTemplate.opsForValue().set(buildSessionIdsKey(sessionId),
                new SessionInformation(principal, sessionId, new Date()));
        principalsTemplate.opsForSet().add(buildPrincipalKey(principal), sessionId);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        sessionIdsTemplate.setConnectionFactory(connectionFactory);
        sessionIdsTemplate.afterPropertiesSet();
        principalsTemplate.setConnectionFactory(connectionFactory);
        principalsTemplate.afterPropertiesSet();
    }

    protected final String buildSessionIdsKey(String sessionId) {
        return RedisSessionRegistry.class.getName() + "_" + sessionId;
    }

    protected final String buildPrincipalsAllKey() {
        return RedisSessionRegistry.class.getName() + "_ALL_LIST";
    }

    protected final String buildPrincipalKey(Object principal) {
        return RedisSessionRegistry.class.getName() + "_" + ((Principal) principal).getName();
    }

    @Override
    public void removeSessionInformation(String sessionId) {
        Assert.hasText(sessionId, "SessionId required as per interface contract");

        SessionInformation info = getSessionInformation(sessionId);

        if (info == null) {
            return;
        }

        if (logger.isTraceEnabled()) {
            logger.debug("Removing session " + sessionId + " from set of registered sessions");
        }

        sessionIdsTemplate.delete(buildSessionIdsKey(sessionId));

        Set<String> sessionsUsedByPrincipal = getSessionsUsedByPrincipal(info.getPrincipal());

        if (sessionsUsedByPrincipal == null) {
            return;
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Removing session " + sessionId + " from principal's set of registered sessions");
        }

        sessionsUsedByPrincipal.remove(sessionId);
        principalsTemplate.opsForSet().remove(buildPrincipalKey(info.getPrincipal()), sessionId);

        if (sessionsUsedByPrincipal.isEmpty()) {
            // No need to keep object in principals Map anymore
            if (logger.isDebugEnabled()) {
                logger.debug("Removing principal " + info.getPrincipal() + " from registry");
            }
            //TODO REMOVE
            //principalsTemplate.Ops.remove(info.getPrincipal());
        }

        if (logger.isTraceEnabled()) {
            logger.trace("Sessions used by '" + info.getPrincipal() + "' : " + sessionsUsedByPrincipal);
        }
    }
}