View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.ws.security.cache;
21  
22  import java.util.Collections;
23  import java.util.Date;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.Set;
27  
28  /**
29   * A simple in-memory HashSet based cache to prevent against replay attacks. The default TTL is 5 minutes
30   * and the max TTL is 60 minutes.
31   */
32  public class MemoryReplayCache implements ReplayCache {
33      
34      public static final long DEFAULT_TTL = 60L * 5L;
35      public static final long MAX_TTL = DEFAULT_TTL * 12L;
36      private Set<ReplayCacheIdentifier> cache = 
37          Collections.synchronizedSet(new HashSet<ReplayCacheIdentifier>());
38      
39      /**
40       * Add the given identifier to the cache. It will be cached for a default amount of time.
41       * @param identifier The identifier to be added
42       */
43      public void add(String identifier) {
44          add(identifier, DEFAULT_TTL);
45      }
46      
47      /**
48       * Add the given identifier to the cache to be cached for the given time
49       * @param identifier The identifier to be added
50       * @param timeToLive The length of time to cache the Identifier in seconds
51       */
52      public void add(String identifier, long timeToLive) {
53          if (identifier == null || "".equals(identifier)) {
54              return;
55          }
56          ReplayCacheIdentifier cacheIdentifier = new ReplayCacheIdentifier();
57          cacheIdentifier.setIdentifier(identifier);
58          
59          long ttl = timeToLive;
60          if (ttl < 0 || ttl > MAX_TTL) {
61              ttl = DEFAULT_TTL;
62          }
63          
64          Date expires = new Date();
65          long currentTime = expires.getTime();
66          expires.setTime(currentTime + (ttl * 1000L));
67          cacheIdentifier.setExpiry(expires);
68          
69          cache.add(cacheIdentifier);
70      }
71      
72      /**
73       * Return true if the given identifier is contained in the cache
74       * @param identifier The identifier to check
75       */
76      public boolean contains(String identifier) {
77          processTokenExpiry();
78          
79          if (identifier != null && !"".equals(identifier)) {
80              ReplayCacheIdentifier cacheIdentifier = new ReplayCacheIdentifier();
81              cacheIdentifier.setIdentifier(identifier);
82              return cache.contains(cacheIdentifier);
83          }
84          return false;
85      }
86      
87      protected void processTokenExpiry() {
88          Date current = new Date();
89          synchronized (cache) {
90              Iterator<ReplayCacheIdentifier> iterator = cache.iterator();
91              while (iterator.hasNext()) {
92                  if (iterator.next().getExpiry().before(current)) {
93                      iterator.remove();
94                  }
95              }
96          }
97      }
98      
99      private static class ReplayCacheIdentifier {
100         
101         private String identifier;
102         private Date expires;
103         
104         /**
105          * Set the (String) identifier
106          * @param identifier the (String) identifier
107          */
108         public void setIdentifier(String identifier) {
109             this.identifier = identifier;
110         }
111         
112         /**
113          * Set when this identifier is to be removed from the cache
114          * @param expires when this identifier is to be removed from the cache
115          */
116         public void setExpiry(Date expires) {
117             this.expires = expires;
118         }
119         
120         /**
121          * Get when this identifier is to be removed from the cache
122          * @return when this identifier is to be removed from the cache
123          */
124         public Date getExpiry() {
125             return expires;
126         }
127         
128         @Override
129         public boolean equals(Object o) {
130             if (this == o) {
131                 return true;
132             }
133             if (!(o instanceof ReplayCacheIdentifier)) {
134                 return false;
135             }
136             
137             ReplayCacheIdentifier replayCacheIdentifier = (ReplayCacheIdentifier)o;
138             
139             if (identifier == null && replayCacheIdentifier.identifier != null) {
140                 return false;
141             } else if (identifier != null && !identifier.equals(replayCacheIdentifier.identifier)) {
142                 return false;
143             }
144             
145             return true;
146         }
147         
148         @Override
149         public int hashCode() {
150             return identifier != null ? identifier.hashCode() : 0;
151         }
152     }
153 
154 }