001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
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: */
016: package edu.yale.its.tp.cas.ticket;
017:
018: import java.security.SecureRandom;
019: import java.util.Collections;
020: import java.util.HashMap;
021: import java.util.Map;
022:
023: /**
024: * Represents a cache of login tickets. These are one-time-use tickets provided on the login page that must be posted back to CAS in
025: * order for a login to be successful. This fixes a bug in IE and Safari where going back through the history causes login
026: * credentials to be reposted to CAS. This class is almost identical to ServiceTicketCache, except it is made to only hold
027: * LoginTickets.
028: */
029: public class LoginTicketCache extends OTUTicketCache {
030:
031: // *********************************************************************
032: // KFSConstants
033:
034: /** Length of random ticket identifiers. */
035: private static final int TICKET_ID_LENGTH = 20;
036:
037: // *********************************************************************
038: // Private state
039:
040: /** The actual cache of tickets (ticketId -> Ticket map) */
041: private Map ticketCache;
042:
043: /** Monotonically increasing serial number for tickets. */
044: private static int serial = 0;
045:
046: // *********************************************************************
047: // Constructor
048:
049: /**
050: * Constructs a new ServiceTicketCache that is intended to store cookies of the given specific ticket type.
051: */
052: public LoginTicketCache(int tolerance) {
053: super (tolerance);
054: this .ticketCache = Collections.synchronizedMap(new HashMap());
055: }
056:
057: // *********************************************************************
058: // Cache-management logic
059:
060: public synchronized String addTicket() throws TicketException {
061: return addTicket(new LoginTicket());
062: }
063:
064: /** Generates and returns a new, unique ticket ID */
065: protected String newTicketId() {
066: // determine appropriate ticketId prefix
067: String prefix = "LT";
068:
069: // produce the random identifier
070: byte[] b = new byte[TICKET_ID_LENGTH];
071: SecureRandom sr = new SecureRandom();
072: sr.nextBytes(b);
073: String ticketId = prefix + "-" + (serial++) + "-"
074: + Util.toPrintable(b);
075:
076: // make sure the identifier isn't already used
077: if (ticketCache.get(ticketId) != null)
078: return newTicketId(); // tail-recurse
079: else
080: return ticketId;
081: }
082:
083: /** Stores the given ticket, associating it with the given identifier. */
084: protected void storeTicket(String ticketId, Ticket t)
085: throws TicketException {
086: // make sure the ticket is valid and new
087: if (ticketCache.get(ticketId) != null)
088: throw new DuplicateTicketException();
089:
090: // if it's okay, then store it
091: ticketCache.put(ticketId, t);
092: }
093:
094: /** Retrieves the ticket with the given identifier. */
095: protected Ticket retrieveTicket(String ticketId) {
096: Object o = ticketCache.get(ticketId);
097: if (o == null)
098: return null;
099: else
100: return (Ticket) o;
101: }
102:
103: /** Removes the ticket from the cache. */
104: public void deleteTicket(String ticketId) {
105: Object o = ticketCache.remove(ticketId);
106: }
107:
108: /** Returns the current ticket serial number (for monitoring) */
109: public int getSerialNumber() {
110: return this .serial;
111: }
112:
113: /** Returns the current number of tickets in the ticket cache. */
114: public int getCacheSize() {
115: return ticketCache.size();
116: }
117: }
|