2 * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package edu.internet2.middleware.shibboleth.idp.session.impl;
19 import java.security.SecureRandom;
21 import org.apache.commons.ssl.util.Hex;
22 import org.joda.time.DateTime;
23 import org.opensaml.util.storage.ExpiringObject;
24 import org.opensaml.util.storage.StorageService;
25 import org.opensaml.xml.util.DatatypeHelper;
27 import org.springframework.context.ApplicationContext;
28 import org.springframework.context.ApplicationContextAware;
30 import edu.internet2.middleware.shibboleth.common.session.LoginEvent;
31 import edu.internet2.middleware.shibboleth.common.session.LogoutEvent;
32 import edu.internet2.middleware.shibboleth.common.session.SessionManager;
33 import edu.internet2.middleware.shibboleth.idp.session.Session;
36 * Manager of IdP sessions.
38 public class SessionManagerImpl implements SessionManager<Session>, ApplicationContextAware {
40 /** Spring context used to publish login and logout events. */
41 private ApplicationContext appCtx;
43 /** Number of random bits within a session ID. */
44 private final int sessionIDSize = 32;
46 /** A {@link SecureRandom} PRNG to generate session IDs. */
47 private final SecureRandom prng = new SecureRandom();
49 /** Backing service used to store sessions. */
50 private StorageService<String, SessionManagerEntry> sessionStore;
52 /** Partition in which entries are stored. */
53 private String partition;
55 /** Lifetime, in milliseconds, of session. */
56 private long sessionLifetime;
61 * @param storageService service used to store sessions
62 * @param lifetime lifetime, in milliseconds, of sessions
64 public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, long lifetime) {
65 sessionStore = storageService;
66 partition = "session";
67 sessionLifetime = lifetime;
73 * @param storageService service used to store session
74 * @param storageParition partition in which sessions are stored
75 * @param lifetime lifetime, in milliseconds, of sessions
77 public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, String storageParition,
79 sessionStore = storageService;
80 if (!DatatypeHelper.isEmpty(storageParition)) {
81 partition = DatatypeHelper.safeTrim(storageParition);
83 partition = "session";
85 sessionLifetime = lifetime;
89 public void setApplicationContext(ApplicationContext applicationContext) {
90 appCtx = applicationContext;
94 public Session createSession(String principal) {
95 // generate a random session ID
96 byte[] sid = new byte[sessionIDSize];
98 String sessionID = Hex.encode(sid);
100 MDC.put("idpSessionId", sessionID);
101 MDC.put("principalName", principal);
103 Session session = new SessionImpl(sessionID, principal, sessionLifetime);
104 SessionManagerEntry sessionEntry = new SessionManagerEntry(this, session, sessionLifetime);
105 sessionStore.put(partition, sessionID, sessionEntry);
106 sessionStore.put(partition, principal, sessionEntry);
107 appCtx.publishEvent(new LoginEvent(session));
112 public void destroySession(String sessionID) {
113 if (sessionID == null) {
117 SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
118 if (sessionEntry != null) {
119 appCtx.publishEvent(new LogoutEvent(sessionEntry.getSession()));
124 public Session getSession(String sessionID) {
125 if (sessionID == null) {
129 SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
130 if (sessionEntry == null) {
134 if (sessionEntry.isExpired()) {
135 destroySession(sessionEntry.getSessionId());
138 return sessionEntry.getSession();
143 public Session getSessionByPrincipalName(String name) {
150 * Session store entry.
152 public class SessionManagerEntry implements ExpiringObject {
154 /** User's session. */
155 private Session userSession;
157 /** Manager that owns the session. */
158 private SessionManager<Session> sessionManager;
160 /** Time this entry expires. */
161 private DateTime expirationTime;
166 * @param manager manager that owns the session
167 * @param session user session
168 * @param lifetime lifetime of session
170 public SessionManagerEntry(SessionManager<Session> manager, Session session, long lifetime) {
171 sessionManager = manager;
172 userSession = session;
173 expirationTime = new DateTime().plus(lifetime);
177 * Gets the user session.
179 * @return user session
181 public Session getSession() {
186 * Gets the ID of the user session.
188 * @return ID of the user session
190 public String getSessionId() {
191 return userSession.getSessionID();
195 public DateTime getExpirationTime() {
196 return expirationTime;
200 public boolean isExpired() {
201 return expirationTime.isBeforeNow();
205 public void onExpire() {
206 sessionManager.destroySession(userSession.getSessionID());