View Javadoc

1   /*
2    * Licensed to the University Corporation for Advanced Internet Development, 
3    * Inc. (UCAID) under one or more contributor license agreements.  See the 
4    * NOTICE file distributed with this work for additional information regarding
5    * copyright ownership. The UCAID licenses this file to You under the Apache 
6    * License, Version 2.0 (the "License"); you may not use this file except in 
7    * compliance with the License.  You may obtain a copy of the License at
8    *
9    *    http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package edu.internet2.middleware.shibboleth.idp.session.impl;
19  
20  import java.security.SecureRandom;
21  
22  import org.apache.commons.ssl.util.Hex;
23  import org.opensaml.util.storage.StorageService;
24  import org.opensaml.xml.util.DatatypeHelper;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  import org.slf4j.MDC;
28  
29  import edu.internet2.middleware.shibboleth.common.session.SessionManager;
30  import edu.internet2.middleware.shibboleth.idp.session.Session;
31  
32  /** Manager of IdP sessions. */
33  public class SessionManagerImpl implements SessionManager<Session> {
34  
35      /** Class logger. */
36      private final Logger log = LoggerFactory.getLogger(SessionManagerImpl.class);
37  
38      /** Number of random bits within a session ID. */
39      private final int sessionIDSize = 32;
40  
41      /** A {@link SecureRandom} PRNG to generate session IDs. */
42      private final SecureRandom prng = new SecureRandom();
43  
44      /** Backing service used to store sessions. */
45      private StorageService<String, SessionManagerEntry> sessionStore;
46  
47      /** Partition in which entries are stored. */
48      private String partition;
49  
50      /** Lifetime, in milliseconds, of session. */
51      private long sessionLifetime;
52  
53      /**
54       * Constructor.
55       * 
56       * @param storageService service used to store sessions
57       * @param lifetime lifetime, in milliseconds, of sessions
58       */
59      public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, long lifetime) {
60          sessionStore = storageService;
61          partition = "session";
62          sessionLifetime = lifetime;
63      }
64  
65      /**
66       * Constructor.
67       * 
68       * @param storageService service used to store session
69       * @param storageParition partition in which sessions are stored
70       * @param lifetime lifetime, in milliseconds, of sessions
71       */
72      public SessionManagerImpl(StorageService<String, SessionManagerEntry> storageService, String storageParition,
73              long lifetime) {
74          sessionStore = storageService;
75          if (!DatatypeHelper.isEmpty(storageParition)) {
76              partition = DatatypeHelper.safeTrim(storageParition);
77          } else {
78              partition = "session";
79          }
80          sessionLifetime = lifetime;
81      }
82  
83      /** {@inheritDoc} */
84      public Session createSession() {
85          // generate a random session ID
86          byte[] sid = new byte[sessionIDSize];
87          prng.nextBytes(sid);
88          String sessionID = Hex.encode(sid);
89          
90          byte[] sessionSecret = new byte[16];
91          prng.nextBytes(sessionSecret);
92  
93          Session session = new SessionImpl(sessionID, sessionSecret, sessionLifetime);
94          SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
95          sessionStore.put(partition, sessionID, sessionEntry);
96  
97          MDC.put("idpSessionId", sessionID);
98          log.trace("Created session {}", sessionID);
99          return session;
100     }
101 
102     /** {@inheritDoc} */
103     public Session createSession(String principal) {
104         // generate a random session ID
105         byte[] sid = new byte[sessionIDSize];
106         prng.nextBytes(sid);
107         String sessionID = Hex.encode(sid);
108         
109         byte[] sessionSecret = new byte[16];
110         prng.nextBytes(sessionSecret);
111 
112         Session session = new SessionImpl(sessionID, sessionSecret, sessionLifetime);
113         SessionManagerEntry sessionEntry = new SessionManagerEntry(session, sessionLifetime);
114         sessionStore.put(partition, sessionID, sessionEntry);
115         
116         MDC.put("idpSessionId", sessionID);
117         log.trace("Created session {}", sessionID);
118         return session;
119     }
120 
121     /** {@inheritDoc} */
122     public void destroySession(String sessionID) {
123         if (sessionID == null) {
124             return;
125         }
126 
127         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
128         if (sessionEntry == null) {
129             return;
130         }
131         for(String sessionIndex : sessionEntry.getSessionIndexes()){
132             sessionStore.remove(partition, sessionIndex);
133         }
134         sessionStore.remove(partition, sessionID);
135     }
136 
137     /** {@inheritDoc} */
138     public Session getSession(String sessionID) {
139         if (sessionID == null) {
140             return null;
141         }
142 
143         SessionManagerEntry sessionEntry = sessionStore.get(partition, sessionID);
144         if (sessionEntry == null) {
145             return null;
146         }
147 
148         if (sessionEntry.isExpired()) {
149             destroySession(sessionEntry.getSessionId());
150             return null;
151         } else {
152             return sessionEntry.getSession();
153         }
154     }
155 
156     /** {@inheritDoc} */
157     public boolean indexSession(Session session, String index) {
158         if (sessionStore.contains(partition, index)) {
159             return false;
160         }
161 
162         SessionManagerEntry sessionEntry = sessionStore.get(partition, session.getSessionID());
163         if (sessionEntry == null) {
164             return false;
165         }
166 
167         if (sessionEntry.getSessionIndexes().contains(index)) {
168             return true;
169         }
170 
171         sessionEntry.getSessionIndexes().add(index);
172         sessionStore.put(partition, index, sessionEntry);
173         log.trace("Added index {} to session {}", index, session.getSessionID());
174         return true;
175     }
176 
177     /** {@inheritDoc} */
178     public void removeSessionIndex(String index) {
179         SessionManagerEntry sessionEntry = sessionStore.remove(partition, index);
180         if (sessionEntry != null) {
181             log.trace("Removing index {} for session {}", index, sessionEntry.getSessionId());
182             sessionEntry.getSessionIndexes().remove(index);
183         }
184     }
185 }