View Javadoc

1   //========================================================================
2   //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
3   //------------------------------------------------------------------------
4   //Licensed under the Apache License, Version 2.0 (the "License");
5   //you may not use this file except in compliance with the License.
6   //You may obtain a copy of the License at 
7   //http://www.apache.org/licenses/LICENSE-2.0
8   //Unless required by applicable law or agreed to in writing, software
9   //distributed under the License is distributed on an "AS IS" BASIS,
10  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  //See the License for the specific language governing permissions and
12  //limitations under the License.
13  //========================================================================
14  
15  package org.mortbay.jetty.servlet;
16  
17  import java.security.SecureRandom;
18  import java.util.Random;
19  
20  import javax.servlet.http.HttpServletRequest;
21  
22  import org.mortbay.component.AbstractLifeCycle;
23  import org.mortbay.jetty.Server;
24  import org.mortbay.jetty.SessionIdManager;
25  import org.mortbay.log.Log;
26  
27  public abstract class AbstractSessionIdManager extends AbstractLifeCycle implements SessionIdManager
28  {
29      private final static String __NEW_SESSION_ID="org.mortbay.jetty.newSessionId";  
30      
31      protected Random _random;
32      protected boolean _weakRandom;
33      protected String _workerName;
34      protected Server _server;
35      
36      
37      public AbstractSessionIdManager(Server server)
38      {
39          _server=server;
40      }
41      
42      
43      public AbstractSessionIdManager(Server server, Random random)
44      {
45          _random=random;
46          _server=server;
47      }
48  
49      public String getWorkerName()
50      {
51          return _workerName;
52      }
53      
54      public void setWorkerName (String name)
55      {
56          _workerName=name;
57      }
58  
59      /* ------------------------------------------------------------ */
60      public Random getRandom()
61      {
62          return _random;
63      }
64  
65      /* ------------------------------------------------------------ */
66      public void setRandom(Random random)
67      {
68          _random=random;
69          _weakRandom=false;
70      }
71      /** 
72       * Create a new session id if necessary.
73       * 
74       * @see org.mortbay.jetty.SessionIdManager#newSessionId(javax.servlet.http.HttpServletRequest, long)
75       */
76      public String newSessionId(HttpServletRequest request, long created)
77      {
78          synchronized (this)
79          {
80              // A requested session ID can only be used if it is in use already.
81              String requested_id=request.getRequestedSessionId();
82              if (requested_id!=null)
83              {
84                  String cluster_id=getClusterId(requested_id);
85                  if (idInUse(cluster_id))
86                      return cluster_id;
87              }
88            
89              // Else reuse any new session ID already defined for this request.
90              String new_id=(String)request.getAttribute(__NEW_SESSION_ID);
91              if (new_id!=null&&idInUse(new_id))
92                  return new_id;
93  
94              
95              
96              // pick a new unique ID!
97              String id=null;
98              while (id==null||id.length()==0||idInUse(id))
99              {
100                 long r0=_weakRandom
101                 ?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^(((long)request.hashCode())<<32))
102                 :_random.nextLong();
103                 if (r0<0)
104                     r0=-r0;
105                 long r1=_weakRandom
106                 ?(hashCode()^Runtime.getRuntime().freeMemory()^_random.nextInt()^(((long)request.hashCode())<<32))
107                 :_random.nextLong();
108                 if (r1<0)
109                     r1=-r1;
110                 id=Long.toString(r0,36)+Long.toString(r1,36);
111                 
112                 //add in the id of the node to ensure unique id across cluster
113                 //NOTE this is different to the node suffix which denotes which node the request was received on
114                 if (_workerName!=null)
115                     id=_workerName + id;
116                 
117             }
118 
119             request.setAttribute(__NEW_SESSION_ID,id);
120             return id;
121         }
122     }
123 
124     public void doStart()
125     {
126        initRandom();
127     }
128 
129     /**
130      * Set up a random number generator for the sessionids.
131      * 
132      * By preference, use a SecureRandom but allow to be injected.
133      */
134     public void initRandom ()
135     {
136         if (_random==null)
137         {
138             try
139             {
140                 _random=new SecureRandom();
141                 _weakRandom=false;
142             }
143             catch (Exception e)
144             {
145                 Log.warn("Could not generate SecureRandom for session-id randomness",e);
146                 _random=new Random();
147                 _weakRandom=true;
148             }
149         }
150         _random.setSeed(_random.nextLong()^System.currentTimeMillis()^hashCode()^Runtime.getRuntime().freeMemory()); 
151     }
152 }