1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server.session;
15
16 import java.security.NoSuchAlgorithmException;
17 import java.security.SecureRandom;
18 import java.util.Random;
19
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpSession;
22
23 import org.eclipse.jetty.server.SessionIdManager;
24 import org.eclipse.jetty.server.session.AbstractSessionManager.Session;
25 import org.eclipse.jetty.util.MultiMap;
26 import org.eclipse.jetty.util.component.AbstractLifeCycle;
27 import org.eclipse.jetty.util.log.Log;
28
29
30
31
32
33 public class HashSessionIdManager extends AbstractLifeCycle implements SessionIdManager
34 {
35 private final static String __NEW_SESSION_ID="org.eclipse.jetty.server.newSessionId";
36 protected final static String SESSION_ID_RANDOM_ALGORITHM = "SHA1PRNG";
37 protected final static String SESSION_ID_RANDOM_ALGORITHM_ALT = "IBMSecureRandom";
38
39 MultiMap<String> _sessions;
40 protected Random _random;
41 private boolean _weakRandom;
42 private String _workerName;
43
44
45 public HashSessionIdManager()
46 {
47 }
48
49
50 public HashSessionIdManager(Random random)
51 {
52 _random=random;
53
54 }
55
56
57
58
59
60
61
62
63 public String getWorkerName()
64 {
65 return _workerName;
66 }
67
68
69
70
71
72
73
74
75 public void setWorkerName(String workerName)
76 {
77 _workerName=workerName;
78 }
79
80
81
82
83
84
85
86 public String getNodeId(String clusterId,HttpServletRequest request)
87 {
88 String worker=request==null?null:(String)request.getAttribute("org.eclipse.http.ajp.JVMRoute");
89 if (worker!=null)
90 return clusterId+'.'+worker;
91
92 if (_workerName!=null)
93 return clusterId+'.'+_workerName;
94
95 return clusterId;
96 }
97
98
99
100
101
102
103
104 public String getClusterId(String nodeId)
105 {
106 int dot=nodeId.lastIndexOf('.');
107 return (dot>0)?nodeId.substring(0,dot):nodeId;
108 }
109
110
111 protected void doStart()
112 {
113 if (_random==null)
114 {
115 try
116 {
117
118
119
120 Log.debug("Init SecureRandom.");
121 _random=SecureRandom.getInstance(SESSION_ID_RANDOM_ALGORITHM);
122 }
123 catch (NoSuchAlgorithmException e)
124 {
125 try
126 {
127 _random=SecureRandom.getInstance(SESSION_ID_RANDOM_ALGORITHM_ALT);
128 _weakRandom=false;
129 }
130 catch (NoSuchAlgorithmException e_alt)
131 {
132 Log.warn("Could not generate SecureRandom for session-id randomness",e);
133 _random=new Random();
134 _weakRandom=true;
135 }
136 }
137 }
138 _random.setSeed(_random.nextLong()^System.currentTimeMillis()^hashCode()^Runtime.getRuntime().freeMemory());
139 _sessions=new MultiMap<String>(true);
140 }
141
142
143 protected void doStop()
144 {
145 if (_sessions!=null)
146 _sessions.clear();
147 _sessions=null;
148 }
149
150
151
152
153
154 public boolean idInUse(String id)
155 {
156 return _sessions.containsKey(id);
157 }
158
159
160
161
162
163 public void addSession(HttpSession session)
164 {
165 _sessions.add(getClusterId(session.getId()),session);
166 }
167
168
169
170
171
172 public void removeSession(HttpSession session)
173 {
174 _sessions.removeValue(getClusterId(session.getId()),session);
175 }
176
177
178
179
180
181 public void invalidateAll(String id)
182 {
183
184
185 while (_sessions.containsKey(id))
186 {
187 Session session=(Session)_sessions.getValue(id,0);
188 if (session.isValid())
189 session.invalidate();
190 else
191 _sessions.removeValue(id,session);
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204 public String newSessionId(HttpServletRequest request, long created)
205 {
206 synchronized (this)
207 {
208
209 String requested_id=request.getRequestedSessionId();
210
211 if (requested_id!=null)
212 {
213 String cluster_id=getClusterId(requested_id);
214 if (idInUse(cluster_id))
215 return cluster_id;
216 }
217
218
219 String new_id=(String)request.getAttribute(__NEW_SESSION_ID);
220 if (new_id!=null&&idInUse(new_id))
221 return new_id;
222
223
224 String id=null;
225 while (id==null||id.length()==0||idInUse(id))
226 {
227 long r=_weakRandom
228 ?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^(((long)request.hashCode())<<32))
229 :_random.nextLong();
230 r^=created;
231 if (request.getRemoteAddr()!=null)
232 r^=request.getRemoteAddr().hashCode();
233 if (r<0)
234 r=-r;
235 id=Long.toString(r,36);
236 }
237
238 request.setAttribute(__NEW_SESSION_ID,id);
239 return id;
240 }
241 }
242
243
244 public Random getRandom()
245 {
246 return _random;
247 }
248
249
250 public void setRandom(Random random)
251 {
252 _random=random;
253 _weakRandom=false;
254 }
255
256 }