Java tutorial
/* * Copyright (c) 2014. * * BaasBox - info-at-baasbox.com * * Licensed 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 com.baasbox.security; import java.util.Date; import java.util.Enumeration; import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; import play.libs.Akka; import play.mvc.Http; import scala.concurrent.duration.FiniteDuration; import akka.actor.Cancellable; import com.baasbox.service.logging.BaasBoxLogger; import com.google.common.collect.ImmutableMap; public class SessionTokenProvider implements ISessionTokenProvider { protected class SessionCleaner implements Runnable { @Override public void run() { BaasBoxLogger.info("Session Cleaner: started"); Enumeration<String> tokens = getTokens(); long totalTokens = 0; long removedTokens = 0; while (tokens.hasMoreElements()) { totalTokens++; if (isExpired(tokens.nextElement())) removedTokens++; } BaasBoxLogger.info("Session cleaner: tokens: " + totalTokens + " - removed: " + removedTokens); BaasBoxLogger.info("Session cleaner: finished"); } } protected final static ConcurrentHashMap<String, ImmutableMap<SessionKeys, ? extends Object>> sessions = new ConcurrentHashMap<String, ImmutableMap<SessionKeys, ? extends Object>>(); protected long expiresInMilliseconds = 0; //default expiration of session tokens protected long sessionClenanerLaunchInMinutes = 60; //the session cleaner will be launch each x minutes. private Cancellable sessionCleaner = null; private static SessionTokenProvider me; private static ISessionTokenProvider initialize() { if (me == null) me = new SessionTokenProvider(); return me; } public static ISessionTokenProvider getSessionTokenProvider() { return initialize(); } public static void destroySessionTokenProvider() { if (me != null && me.sessionCleaner != null) { me.sessionCleaner.cancel(); BaasBoxLogger.info("Session Cleaner: cancelled"); } me = null; } public SessionTokenProvider() { setTimeout(expiresInMilliseconds); startSessionCleaner(sessionClenanerLaunchInMinutes * 60000); //converts minutes in milliseconds }; public void setTimeout(long timeoutInMilliseconds) { this.expiresInMilliseconds = timeoutInMilliseconds; if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("New session timeout: " + timeoutInMilliseconds + " ms"); } //setTimeout @Override public ImmutableMap<SessionKeys, ? extends Object> setSession(String AppCode, String username, String password) { UUID token = UUID.randomUUID(); ImmutableMap<SessionKeys, ? extends Object> info = ImmutableMap.of(SessionKeys.APP_CODE, AppCode, SessionKeys.TOKEN, token.toString(), SessionKeys.USERNAME, username, SessionKeys.PASSWORD, password, SessionKeys.EXPIRE_TIME, (new Date()).getTime() + expiresInMilliseconds); sessions.put(token.toString(), info); return info; } @Override public ImmutableMap<SessionKeys, ? extends Object> getSession(String token) { if (isExpired(token)) { return null; } ImmutableMap<SessionKeys, ? extends Object> info = sessions.get(token); ImmutableMap<SessionKeys, ? extends Object> newInfo = ImmutableMap.of(SessionKeys.APP_CODE, info.get(SessionKeys.APP_CODE), SessionKeys.TOKEN, token, SessionKeys.USERNAME, info.get(SessionKeys.USERNAME), SessionKeys.PASSWORD, info.get(SessionKeys.PASSWORD), SessionKeys.EXPIRE_TIME, (new Date()).getTime() + expiresInMilliseconds); sessions.put(token, newInfo); return newInfo; } @Override public void removeSession(String token) { if (BaasBoxLogger.isDebugEnabled()) BaasBoxLogger.debug("SessionTokenProvider: " + token + " removed"); sessions.remove(token); } @Override public Enumeration<String> getTokens() { return sessions.keys(); } private boolean isExpired(String token) { ImmutableMap<SessionKeys, ? extends Object> info = sessions.get(token); if (info == null) return true; if (expiresInMilliseconds != 0 && (new Date()).getTime() > (Long) info.get(SessionKeys.EXPIRE_TIME)) { removeSession(token); return true; } return false; } private void startSessionCleaner(long timeoutInMilliseconds) { sessionCleaner = Akka.system().scheduler().schedule(new FiniteDuration(1000, TimeUnit.MILLISECONDS), new FiniteDuration(timeoutInMilliseconds, TimeUnit.MILLISECONDS), new SessionCleaner(), Akka.system().dispatcher()); } @Override public List<ImmutableMap<SessionKeys, ? extends Object>> getSessions(String username) { Stream<ImmutableMap<SessionKeys, ? extends Object>> values = sessions.values().stream() .filter(x -> x.get(SessionKeys.USERNAME).equals(username)); List<ImmutableMap<SessionKeys, ? extends Object>> toRet = values.collect(Collectors.toList()); return toRet; } @Override public ImmutableMap<SessionKeys, ? extends Object> getCurrent() { String token = (String) Http.Context.current().args.get("token"); if (token != null) return sessions.get(token); else return null; } }