View Javadoc

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.opensaml.util.storage.StorageService;
23  import org.opensaml.xml.util.DatatypeHelper;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  import org.slf4j.MDC;
27  
28  import edu.internet2.middleware.shibboleth.common.session.SessionManager;
29  import edu.internet2.middleware.shibboleth.idp.session.Session;
30  
31  /** Manager of IdP sessions. */
32  public class SessionManagerImpl implements SessionManager<Session> {
33  
34      /** Class logger. */
35      private final Logger log = LoggerFactory.getLogger(SessionManagerImpl.class);
36  
37      /** Number of random bits within a session ID. */
38      private final int sessionIDSize = 32;
39  
40      /** A {@link SecureRandom} PRNG to generate session IDs. */
41      private final SecureRandom prng = new SecureRandom();
42  
43      /** Backing service used to store sessions. */
44      private StorageService<String, SessionManagerEntry> sessionStore;
45  
46      /** Partition in which entries are stored. */
47      private String partition;
48  
49      /** Lifetime, in milliseconds, of session. */
50      private long sessionLifetime;
51  
52      /**
53       * Constructor.
54       * 
55       * @param storageService service used to store sessions
56       * @param lifetime lifetime, in milliseconds, of sessions
57       */
58      public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, long lifetime) {
59          sessionStore = storageService;
60          partition = "session";
61          sessionLifetime = lifetime;
62      }
63  
64      /**
65       * Constructor.
66       * 
67       * @param storageService service used to store session
68       * @param storageParition partition in which sessions are stored
69       * @param lifetime lifetime, in milliseconds, of sessions
70       */
71      public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, String storageParition,
72              long lifetime) {
73          sessionStore = storageService;
74          if (!DatatypeHelper.isEmpty(storageParition)) {
75              partition = DatatypeHelper.safeTrim(storageParition);
76          } else {
77              partition = "session";
78          }
79          sessionLifetime = lifetime;
80      }
81  
82      /** {@inheritDoc} */
83      public Session createSession() {
84          // generate a random session ID
85          byte[] sid = new byte[sessionIDSize];
86          prng.nextBytes(sid);
87          String sessionID = Hex.encode(sid);
88          
89          byte[] sessionSecret = new byte[16];
90          prng.nextBytes(sessionSecret);
91  
92          Session session = new SessionImpl(sessionID, sessionSecret, sessionLifetime);
93          SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
94          sessionStore.put(partition, sessionID, sessionEntry);
95  
96          MDC.put("idpSessionId", sessionID);
97          log.trace("Created session {}", sessionID);
98          return session;
99      }
100 
101     /** {@inheritDoc} */
102     public Session createSession(String principal) {
103         // generate a random session ID
104         byte[] sid = new byte[sessionIDSize];
105         prng.nextBytes(sid);
106         String sessionID = Hex.encode(sid);
107         
108         byte[] sessionSecret = new byte[16];
109         prng.nextBytes(sessionSecret);
110 
111         Session session = new SessionImpl(sessionID, sessionSecret, sessionLifetime);
112         SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
113         sessionStore.put(partition, sessionID, sessionEntry);
114         
115         MDC.put("idpSessionId", sessionID);
116         log.trace("Created session {}", sessionID);
117         return session;
118     }
119 
120     /** {@inheritDoc} */
121     public void destroySession(String sessionID) {
122         if (sessionID == null) {
123             return;
124         }
125 
126         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
127         if (sessionEntry == null) {
128             return;
129         }
130         for(String sessionIndex : sessionEntry.getSessionIndexes()){
131             sessionStore.remove(partition, sessionIndex);
132         }
133         sessionStore.remove(partition, sessionID);
134     }
135 
136     /** {@inheritDoc} */
137     public Session getSession(String sessionID) {
138         if (sessionID == null) {
139             return null;
140         }
141 
142         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
143         if (sessionEntry == null) {
144             return null;
145         }
146 
147         if (sessionEntry.isExpired()) {
148             destroySession(sessionEntry.getSessionId());
149             return null;
150         } else {
151             return sessionEntry.getSession();
152         }
153     }
154 
155     /** {@inheritDoc} */
156     public boolean indexSession(Session session, String index) {
157         if (sessionStore.contains(partition, index)) {
158             return false;
159         }
160 
161         SessionManagerEntry sessionEntry = sessionStore.get(partition, session.getSessionID());
162         if (sessionEntry == null) {
163             return false;
164         }
165 
166         if (sessionEntry.getSessionIndexes().contains(index)) {
167             return true;
168         }
169 
170         sessionEntry.getSessionIndexes().add(index);
171         sessionStore.put(partition, index, sessionEntry);
172         log.trace("Added index {} to session {}", index, session.getSessionID());
173         return true;
174     }
175 
176     /** {@inheritDoc} */
177     public void removeSessionIndex(String index) {
178         SessionManagerEntry sessionEntry = sessionStore.remove(partition, index);
179         if (sessionEntry != null) {
180             log.trace("Removing index {} for session {}", index, sessionEntry.getSessionId());
181             sessionEntry.getSessionIndexes().remove(index);
182         }
183     }
184 }