Make IdP session ID and principal name available to logging framerwork for inclusion...
[java-idp.git] / src / main / java / edu / internet2 / middleware / shibboleth / idp / session / impl / SessionManagerImpl.java
1 /*
2  * Copyright [2007] [University Corporation for Advanced Internet Development, Inc.]
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package edu.internet2.middleware.shibboleth.idp.session.impl;
18
19 import java.security.SecureRandom;
20
21 import org.apache.commons.ssl.util.Hex;
22 import org.apache.log4j.MDC;
23 import org.joda.time.DateTime;
24 import org.opensaml.util.storage.ExpiringObject;
25 import org.opensaml.util.storage.StorageService;
26 import org.opensaml.xml.util.DatatypeHelper;
27 import org.springframework.context.ApplicationContext;
28 import org.springframework.context.ApplicationContextAware;
29
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;
34
35 /**
36  * Manager of IdP sessions.
37  */
38 public class SessionManagerImpl implements SessionManager<Session>, ApplicationContextAware {
39
40     /** Spring context used to publish login and logout events. */
41     private ApplicationContext appCtx;
42
43     /** Number of random bits within a session ID. */
44     private final int sessionIDSize = 32;
45
46     /** A {@link SecureRandom} PRNG to generate session IDs. */
47     private final SecureRandom prng = new SecureRandom();
48
49     /** Backing service used to store sessions. */
50     private StorageService<String, SessionManagerEntry> sessionStore;
51
52     /** Partition in which entries are stored. */
53     private String partition;
54
55     /** Lifetime, in milliseconds, of session. */
56     private long sessionLifetime;
57
58     /**
59      * Constructor.
60      * 
61      * @param storageService service used to store sessions
62      * @param lifetime lifetime, in milliseconds, of sessions
63      */
64     public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, long lifetime) {
65         sessionStore = storageService;
66         partition = "session";
67         sessionLifetime = lifetime;
68     }
69
70     /**
71      * Constructor.
72      * 
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
76      */
77     public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, String storageParition,
78             long lifetime) {
79         sessionStore = storageService;
80         if (!DatatypeHelper.isEmpty(storageParition)) {
81             partition = DatatypeHelper.safeTrim(storageParition);
82         } else {
83             partition = "session";
84         }
85         sessionLifetime = lifetime;
86     }
87
88     /** {@inheritDoc} */
89     public void setApplicationContext(ApplicationContext applicationContext) {
90         appCtx = applicationContext;
91     }
92
93     /** {@inheritDoc} */
94     public Session createSession(String principal) {
95         // generate a random session ID
96         byte[] sid = new byte[sessionIDSize];
97         prng.nextBytes(sid);
98         String sessionID = Hex.encode(sid);
99
100         MDC.put("idpSessionId", sessionID);
101         MDC.put("principalName", principal);
102         
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));
108         return session;
109     }
110
111     /** {@inheritDoc} */
112     public void destroySession(String sessionID) {
113         if (sessionID == null) {
114             return;
115         }
116
117         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
118         if (sessionEntry != null) {
119             appCtx.publishEvent(new LogoutEvent(sessionEntry.getSession()));
120         }
121     }
122
123     /** {@inheritDoc} */
124     public Session getSession(String sessionID) {
125         if (sessionID == null) {
126             return null;
127         }
128
129         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
130         if (sessionEntry == null) {
131             return null;
132         }
133
134         if (sessionEntry.isExpired()) {
135             destroySession(sessionEntry.getSessionId());
136             return null;
137         } else {
138             return sessionEntry.getSession();
139         }
140     }
141
142     /** {@inheritDoc} */
143     public Session getSessionByPrincipalName(String name) {
144
145         // TODO
146         return null;
147     }
148
149     /**
150      * Session store entry.
151      */
152     public class SessionManagerEntry implements ExpiringObject {
153
154         /** User's session. */
155         private Session userSession;
156
157         /** Manager that owns the session. */
158         private SessionManager<Session> sessionManager;
159
160         /** Time this entry expires. */
161         private DateTime expirationTime;
162
163         /**
164          * Constructor.
165          * 
166          * @param manager manager that owns the session
167          * @param session user session
168          * @param lifetime lifetime of session
169          */
170         public SessionManagerEntry(SessionManager<Session> manager, Session session, long lifetime) {
171             sessionManager = manager;
172             userSession = session;
173             expirationTime = new DateTime().plus(lifetime);
174         }
175
176         /**
177          * Gets the user session.
178          * 
179          * @return user session
180          */
181         public Session getSession() {
182             return userSession;
183         }
184
185         /**
186          * Gets the ID of the user session.
187          * 
188          * @return ID of the user session
189          */
190         public String getSessionId() {
191             return userSession.getSessionID();
192         }
193
194         /** {@inheritDoc} */
195         public DateTime getExpirationTime() {
196             return expirationTime;
197         }
198
199         /** {@inheritDoc} */
200         public boolean isExpired() {
201             return expirationTime.isBeforeNow();
202         }
203
204         /** {@inheritDoc} */
205         public void onExpire() {
206             sessionManager.destroySession(userSession.getSessionID());
207         }
208     }
209 }