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 }