2009/05/20 - Apache Shale has been retired.
For more information, please explore the Attic.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shale.util;
19
20 import java.security.MessageDigest;
21 import java.security.NoSuchAlgorithmException;
22 import java.util.HashSet;
23 import java.util.Set;
24
25 import javax.faces.FacesException;
26 import javax.faces.context.FacesContext;
27 import javax.faces.el.PropertyResolver;
28
29 import org.apache.shale.faces.ShaleConstants;
30
31 /***
32 * <p>Utility methods supporting the generation and validation of transaction
33 * tokens, used to avoid duplicate form submits.</p>
34 *
35 * $Id: TokenProcessor.java 464373 2006-10-16 04:21:54Z rahul $
36 */
37 public class TokenProcessor {
38
39
40
41
42
43 /***
44 * <p>Timestamp most recently used to generate a transaction token value.</p>
45 */
46 private long previous;
47
48
49
50
51
52 /***
53 * <p>Generate and return the next transaction token value, and store it
54 * so that it may be verified on a subsequent form submit.</p>
55 *
56 * @param context <code>FacesContext</code> for the current request
57 */
58 public synchronized String generate(FacesContext context) {
59
60
61
62 Object session = context.getExternalContext().getSession(true);
63 assert session != null;
64 PropertyResolver pr = context.getApplication().getPropertyResolver();
65 assert pr != null;
66 byte id[] = ((String) pr.getValue(session, "id")).getBytes();
67
68
69 long current = System.currentTimeMillis();
70 if (current <= previous) {
71 current = previous + 1;
72 }
73 previous = current;
74
75 byte now[] = Long.toString(current).getBytes();
76
77
78 String token = null;
79 try {
80 MessageDigest md = MessageDigest.getInstance("MD5");
81 md.update(id);
82 md.update(now);
83 token = toHex(md.digest());
84 } catch (NoSuchAlgorithmException e) {
85 throw new FacesException(e);
86 }
87
88
89 Set set = (Set)
90 context.getExternalContext().getSessionMap().get(ShaleConstants.TOKENS);
91 if (set == null) {
92 set = new HashSet();
93 context.getExternalContext().getSessionMap().put(ShaleConstants.TOKENS, set);
94 }
95 set.add(token);
96
97
98 return token;
99
100 }
101
102
103 /***
104 * <p>Verify that the specified transaction token value (retrieved from an
105 * incoming request) is a valid transaaction token. In addition, remove it
106 * from any stored cache of tokens, so that it may not be reused.</p>
107 *
108 * @param context <code>FacesContext</code> for the current request
109 * @param token Transaction token to be verified
110 *
111 * @return <code>True</code> if this token has been verified,
112 * else <code>false</code>
113 */
114 public synchronized boolean verify(FacesContext context, String token) {
115
116 Set set = (Set)
117 context.getExternalContext().getSessionMap().get(ShaleConstants.TOKENS);
118 if (set == null) {
119 return false;
120 }
121 if (set.contains(token)) {
122 set.remove(token);
123 if (set.size() < 1) {
124 context.getExternalContext().getSessionMap().remove(ShaleConstants.TOKENS);
125 }
126 return true;
127 }
128 return false;
129
130 }
131
132
133
134
135
136 /***
137 * <p>Convert the specified byte array into a String of hexadecimal
138 * digit characters.</p>
139 *
140 * @param buffer Byte array to be converted
141 */
142 private String toHex(byte buffer[]) {
143
144 StringBuffer sb = new StringBuffer(buffer.length * 2);
145 for (int i = 0; i < buffer.length; i++) {
146 sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
147 sb.append(Character.forDigit((buffer[i] & 0x0f), 16));
148 }
149 return sb.toString();
150
151 }
152
153
154 }