001/** 002 * Copyright 2014 Tampere University of Technology, Pori Department 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package core.tut.pori.context; 017 018import org.apache.log4j.Logger; 019import org.springframework.security.core.session.SessionInformation; 020import org.springframework.security.core.session.SessionRegistry; 021 022import core.tut.pori.users.UserIdentity; 023 024/** 025 * Accessible interface to active Sessions within the web application (service) context. 026 * 027 * This class can be used to register new sessions and retrieve information for a particular session. 028 * The session information is provided for all services, though the session management is generally handled internally and modifying the active sessions may cause undefined behavior. 029 * 030 * One should not initialize this handler directly, as an instantiated version is available from ServiceInitializer. 031 */ 032public class SessionHandler { 033 private static final Logger LOGGER = Logger.getLogger(SessionHandler.class); 034 private static SessionHandler _handler = new SessionHandler(); 035 private SessionHandlerPrivate _handlerPrivate = null; 036 037 /** 038 * 039 * @param handler 040 */ 041 private static synchronized void setHandler(SessionHandlerPrivate handler){ 042 if(handler == null){ 043 LOGGER.debug("Removing handler..."); 044 }else if(_handler._handlerPrivate != null){ 045 LOGGER.warn("Replacing previous handler..."); 046 } 047 _handler.setHandlerPrivate(handler); 048 } 049 050 /** 051 * 052 * @return the session handler 053 */ 054 public static SessionHandler getSessionHandler(){ 055 return _handler; 056 } 057 058 /** 059 * 060 */ 061 private SessionHandler(){ 062 // nothing needed 063 } 064 065 /** 066 * @param sessionId 067 * @return session information 068 * @see org.springframework.security.core.session.SessionRegistry#getSessionInformation(java.lang.String) 069 */ 070 public SessionInformation getSessionInformation(String sessionId) { 071 if(_handlerPrivate == null){ 072 LOGGER.debug("Session registry not available."); 073 return null; 074 }else{ 075 LOGGER.debug("Retrieving session information for sessionId: "+sessionId); 076 return _handlerPrivate.getSessionRegistry().getSessionInformation(sessionId); // in principle we should synchronize and check if registry is available, but in practice it will never NOT be available 077 } 078 } 079 080 /** 081 * @param sessionId 082 * @param userId 083 * @see org.springframework.security.core.session.SessionRegistry#registerNewSession(java.lang.String, java.lang.Object) 084 * @throws IllegalStateException if registry is not available 085 */ 086 public void registerNewSession(String sessionId, UserIdentity userId) throws IllegalStateException{ 087 if(_handlerPrivate == null){ 088 throw new IllegalStateException("Session registry not available."); 089 } 090 LOGGER.debug("Registering new session for sessionId: "+sessionId+", userId: "+userId.getUserId()); 091 _handlerPrivate.getSessionRegistry().registerNewSession(sessionId, userId); // in principle we should synchronize and check if registry is available, but in practice it will never NOT be available 092 } 093 094 /** 095 * This is essentially the same as calling LoginHandler.authentice() and registerNewSession() 096 * 097 * @param sessionId 098 * @param userId 099 * @throws IllegalStateException 100 */ 101 public void registerAndAuthenticate(String sessionId, UserIdentity userId) throws IllegalStateException{ 102 LoginHandler.authenticate(userId); 103 registerNewSession(sessionId, userId); 104 } 105 106 /** 107 * @param sessionId 108 * @see org.springframework.security.core.session.SessionRegistry#removeSessionInformation(java.lang.String) 109 */ 110 public void removeSessionInformation(String sessionId) { 111 if(_handlerPrivate == null){ 112 LOGGER.debug("Session registry not available."); 113 }else{ 114 LOGGER.debug("Removing session information for sessionId: "+sessionId); 115 _handlerPrivate.getSessionRegistry().removeSessionInformation(sessionId); // in principle we should synchronize and check if registry is available, but in practice it will never NOT be available 116 } 117 } 118 119 /** 120 * Note: this is NOT synchronized, which means that it may be possible for the user to re-login whilst the operation is in progress, if this is called for user account removal, 121 * remember to FIRST remove the account to make sure user cannot re-login 122 * 123 * @param userId 124 */ 125 public void removeSessionInformation(UserIdentity userId){ 126 if(_handlerPrivate == null){ // in principle we should synchronize and check if registry is available, but in practice it will never NOT be available 127 LOGGER.debug("Session registry not available."); 128 }else{ 129 LOGGER.debug("Removing session information for userId: "+userId.getUserId()); 130 SessionRegistry registry = _handlerPrivate.getSessionRegistry(); 131 for(Object principal : registry.getAllPrincipals()){ // check all principals, note that simply asking for all sessions for the given userId object (principal) may not work as there might be slight differences between the passed object and the one known by the system, which may fool the equals check 132 if(principal.getClass() != UserIdentity.class){ 133 continue; 134 } 135 UserIdentity pIdentity = (UserIdentity) principal; 136 if(UserIdentity.equals(userId, (UserIdentity) principal)){ 137 for(SessionInformation sessionInformation : registry.getAllSessions(pIdentity, true)){ 138 _handlerPrivate.getSessionRegistry().removeSessionInformation(sessionInformation.getSessionId()); 139 } // for session information 140 } // if equals 141 } // for 142 } // else 143 } 144 145 /** 146 * @param handlerPrivate the handlerPrivate to set 147 */ 148 private void setHandlerPrivate(SessionHandlerPrivate handlerPrivate) { 149 _handlerPrivate = handlerPrivate; 150 } 151 152 /** 153 * Private instance of session handler. 154 * 155 * Created as a bean. 156 */ 157 private static class SessionHandlerPrivate{ 158 private SessionRegistry _sessionRegistry = null; 159 160 /** 161 * 162 * @param sessionRegistry 163 */ 164 @SuppressWarnings("unused") 165 public SessionHandlerPrivate(SessionRegistry sessionRegistry){ 166 _sessionRegistry = sessionRegistry; 167 } 168 169 /** 170 * Called by bean initialization 171 */ 172 @SuppressWarnings("unused") 173 public void initialized(){ 174 LOGGER.debug("Initialized."); 175 setHandler(this); 176 } 177 178 /** 179 * Called when bean is destroyed 180 */ 181 @SuppressWarnings("unused") 182 public void destroyed(){ 183 LOGGER.debug("Destroyed."); 184 setHandler(null); 185 } 186 187 /** 188 * @return the sessionRegistry 189 */ 190 public SessionRegistry getSessionRegistry() { 191 return _sessionRegistry; 192 } 193 } // class SessionHandlerPrivate 194}