- /**
- * Copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Permission to use, copy, modify, and distribute this software
- * and its documentation for NON-COMMERCIAL purposes and without
- * fee is hereby granted provided that this copyright notice
- * appears in all copies. Please refer to the file "copyright.html"
- * for further important copyright and licensing information.
- *
- * The Java source code is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You shall
- * not disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
- * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
- */
- import java.io.*;
- import javax.servlet.*;
- import javax.servlet.http.*;
- import sun.server.http.*;
- import sun.misc.*;
- import sun.servlet.http.Cookie;
- import java.util.*;
-
- /**
- *
- * On startup, the servlet looks for the following
parameters:
- * flush - how much time to wait before flushing
sessions.
- * cookieTimeout - how much time a session
"lives".
- *domain - domain used for the cookie.
- *home - name of the Home html document you
want users to be directed too after an
initial log in.
- *loginFirst - full path/name of the initial
Login page served to
the client when first accessing the site.
- *loginInvalid - full path/name of the login
page served if the
userid/password is invalid.
- *authenticator - a Authenicator implementation.
- *
- * The login must do a POST from a forum/applet
with the following values:
- *UserId=<users id>
- * Password=<users password>
- * action="login"
- *
- *If a session is valid, the either FileServlet or
SSIncludeServlet is responsible for serving the
- * file to the user.
- *
- * Users are authorized via a abstract method
"isAuthorized" in the
Authenciator interface.
- *
- * @author Tony Squier
- * @version 1.8 97/02/10 13:29:25
- */
-
-
- public class SessionServlet extends HttpServlet
implements Runnable
- {
- /**
- * Servlets context
- */
- protected ServletContext context;
-
- /**
- * Helper servlets: File and SSInlcude
- */
- protected SSIncludeServlet ssIncludeServlet;
- protected FileServlet fileServlet;
-
- /**
- * Authenticator
- */
- private Authenticator auth;
-
- /**
- * Restricted domain
- */
- protected String domain;
-
- /**
- * Timeout for sessions
- */
- protected long sessionTimeout;
- protected Thread tid;
- protected Hashtable sessionCache;
- protected long flush;
-
-
- /**
- * Login Template Name
- */
- protected String homeHtml;
-
- protected String loginFirstHtml;
- protected String loginInvalidHtml;
-
-
- /**
- * Initialize the Servlet and set the html pages.
- * @param stub Arguments passed by the Servlet loader
- * @return void
- */
- public void init (ServletConfig config) throws
ServletException
- {
- super.init(config);
-
- context = config.getServletContext();
- ssIncludeServlet =
(SSIncludeServlet)context.getServlet (
"ssinclude");
- fileServlet = (FileServlet)context.getServlet (
"file");
-
- try
- {
- auth =
(Authenticator)Class.forName(
config.getInitParameter(
"auth")).newInstance();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
-
- homeHtml = config.getInitParameter ("home");
- loginFirstHtml = config.getInitParameter (
"loginFirst");
- loginInvalidHtml =
config.getInitParameter ("loginInvalid");
-
- domain = config.getInitParameter ("domain");
-
- flush = Long.parseLong (
config.getInitParameter("flush"));
- sessionTimeout =
Long.parseLong (
config.getInitParameter("cookieTimeout"));
- sessionCache = new Hashtable();
-
- tid = new Thread(this);
- tid.setPriority (Thread.MIN_PRIORITY);
- tid.start();
- }
-
- /**
- * Main service routine for the Servlet. This
method is responsible for checking
- * the request and determining the appropriate
action: login or serve pages.
- *
- * Subclasses shouldn't override this method,
but rather override startSession,
- * endSession, and serviceRequest. If this
method is overridden, you must
- * invoke it from the extended method or
Session tracking may/may not occur
- * correctly
- * @param request The Servlet request.
- * @param response The Servlet response.
- * @return void.
- */
- public void service (HttpServletRequest request,
HttpServletResponse response) throws
ServletException, IOException
- {
- // Get the session associated with the request. If
- // none exists, session is set to null.
- Session session =
_validateSession (request);
-
- // Since we may be chained, we will
- // just send the cookie along its way for
- // other servlets to consume
- if ( session != null )
- {
- response.setHeader ("Cookie",
"SessionServlet="+session.getId());
- }
-
- // Determine what we are being asked to do
by looking
- // at the action field first.
- // If action is set, then check it, otherwise, simply
- // service the request via the serviceRequest method.
- String action;
- if ( (action=request.getParameter (
"action")) != null )
- {
- _performAction (action, session, request, response);
- }
- // No action value, so service the request by
- // calling serviceRequest method.
- else
- {
- if ( session != null )
- {
- serviceRequest (session, request, response);
- }
- else
- {
- response.sendRedirect (
"/servlet/SessionServlet?action=showLogin");
- }
- }
- }
-
- /**
- * Method called by the service routine if
a valid Session
- * exists and a request can be served.
- * @param session The session.
- * @param request The Original HttpServletRequest.
- * @param response The Original HttpServletResponse.
- * @throws IOException
- * @throws ServletException
- * @return void
- */
- protected void serviceRequest (
Session session, HttpServletRequest
request, HttpServletResponse response)
throws IOException, ServletException
- {
- /**
- * Set the Session's URI path so we know where
this session is going.
- * We only track .html and .shtml files
- */
- if ( context.getMimeType (
request.getRequestURI()).equals
("text/html") ||
- context.getMimeType (request.getRequestURI()).equals
("java-internal/parsed-html") ||
- request.getRequestURI().endsWith ("/") )
- {
- session.setURI (request.getRequestURI());
- }
- response.setHeader ("Expires",
String.valueOf (session.getExpires()));
- if ( request.getRequestURI().lastIndexOf (
".") == -1
&& request.getRequestURI().endsWith (
"/") == false )
- {
- ((sun.server.http.HttpServiceRequest)request).setPathInfo
(request.getRequestURI()+"/");
- }
- else
- {
- ((sun.server.http.HttpServiceRequest)request).setPathInfo
(request.getRequestURI());
- }
- if ( context.getMimeType (
request.getRequestURI()).equals
("java-internal/parsed-html") )
- {
- ssIncludeServlet.service (request, response);
- }
- else
- {
- fileServlet.service (request, response);
- }
- }
-
- /**
- * Starts a new Session. A new Session is
started by first
- * creating a new Session instance, putting
it into the SessionCache
- * and setting the Cookie with the SessionId
- * @param userId The user Id.
- * @param password The Password.
- * @param response The HttpServletResponse
used for setting the Cookie
- * @throws IOException
- * @throws ServletException
- * @return Session Null if authentication failed
- */
- protected Session startSession (String userId,
String password,
HttpServletResponse response)
- {
- Session session = null;
- if ( auth.isAuthorized (userId, password) )
- {
- // Create a session
- session = new Session (userId);
- session.setExpires (
sessionTimeout+System.currentTimeMillis());
- sessionCache.put (session.key(), session);
-
- // Create a client cookie
- Cookie c = new Cookie("SessionServlet",
String.valueOf (session.getId()));
- c.setPath ("/");
- c.setMaxAge (-1);
- c.setDomain (domain);
-
- response.setHeader ("Set-Cookie",
"SessionServlet=" +
- c.getValue() +
- "; Domain=" +
- c.getDomain() +
- "; Path=" + c.getPath());
-
- }
- return session;
- }
-
- /**
- * Method invoked to terminate a Session
- * @param session The Session to terminate
- * @return void
- */
- protected void endSession (Session session)
- {
- synchronized (sessionCache)
- {
- sessionCache.remove (session.key());
- }
- }
-
-
- /**
- * Default page servicing routine. A InputStream
contains the page that is
- * written to the Servlet's output stream.
Neither the in or out Streams
- * are closed when finished!
- * @param in Contents are read from.
- * @param out Contents are copied into
- * @return void
- * @throws IOException
- */
- protected void copyInToOut (BufferedInputStream in,
BufferedOutputStream out) throws IOException
- {
- int length;
- byte data[] = new byte[8192];
- while ( (length=in.read(data)) != -1 )
- {
- out.write (data, 0, length);
- }
- }
-
- /**
- * Retrives and Validates Session
- * @param request HttpServletRequest
- * @return Session Session or null
- */
- private
Session _validateSession
(HttpServletRequest request)
- {
- Cookie c[] = Cookie.getCookies (request);
- Session session;
- if ( c != null && c.length == 1 )
- {
- String key = String.valueOf (c[0].getValue());
- session = (Session)sessionCache.get (key);
- }
- else
- {
- session = null;
- }
- return session;
- }
-
- /**
- * Convience method to handle posts which set
the action hidden field
- * This is the main routine the does most
of the work. See comments
- * in service method.
- * @param action The value of action
- * @param session The session.
- * @param request The HttpServletRequest.
- * @param response The HttpServletResponse.
- * @return void
- * @throws IOException
- * @throws ServletException
- */
- private void _performAction (
String action, Session session,
HttpServletRequest request, HttpServletResponse
response) throws IOException, ServletException
- {
- response.setHeader ("Pragma",
"no-cache");
-
- // Invoke startSession method.
- if ( action.equals ("login") )
- {
- // Start a new Session and redirect to
client's original destination if
- // true is returned.
- Session s;
- if ( (s=startSession (request.getParameter
("UserId"), request.getParameter (
"Password"), response))!= null )
- {
- response.sendRedirect (homeHtml);
- }
- // Authenticator failed, so return the client
the showInvalid page.
- else
- {
- response.setContentType ("text/html");
- response.sendRedirect (
"/servlet/SessionServlet?action=
showInvalid");
- }
- }
- // Remove session, if one exists, from session cache.
- // Send the client back to the loginFirstHtml page.
- else if ( action.equals ("logout") )
- {
- if ( session != null )
- {
- endSession (session);
- }
- response.sendRedirect (
"/servlet/SessionServlet?action=showLogin");
- }
- // If show request, determine which page
- // and show it. We only allow this if the
- // user isn't logged into the SessionServlet.
- else if ( action.startsWith ("show") )
- {
- if ( session == null )
- {
- String page;
- if ( action.equals ("showInvalid") )
- {
- page = loginInvalidHtml;
- }
- else
- {
- page = loginFirstHtml;
- }
-
- // If we are not logged in, i.e. no Session, then
- // show the login page. Otherwise, if a valid
Session exists,
- // we don't want to un-necessarly show the
login page, so
- // re-send back to the homeHtml page. This way
we don't
- // get multiple Sessions for a single client because
- // they continually logged in multiple times.
- //
- // This is the only time we explictly serve
up a file, so
- // we write to the output stream for the
response and
- // close it when we are done.
- BufferedInputStream inputStream =
new BufferedInputStream
(new FileInputStream (page));
- response.setContentType ("text/html");
- copyInToOut (inputStream,
new BufferedOutputStream
(response.getOutputStream()));
- response.getOutputStream().flush();
- response.getOutputStream().close();
- inputStream.close();
- }
- else
- {
- response.sendRedirect (homeHtml);
- }
- }
- // Show the currently cached sessions
- else if ( action.equals
("cache-peek") )
- {
- PrintStream print =
new PrintStream (response.getOutputStream());
- Thread.currentThread().setPriority (
Thread.MIN_PRIORITY);
- Enumeration sessions;
- synchronized (sessionCache)
- {
- sessions = sessionCache.elements();
- }
- while ( sessions.hasMoreElements() )
- {
- Session s = (Session)sessions.nextElement();
- print.println (s.getId()+":"+s.getURI());
- Thread.yield();
- }
- print.flush();
- sessions = null;
- }
- // Otherwise, no valid action value is set, so
- // send them to the login page.
- else
- {
- response.sendRedirect (
"/servlet/SessionServlet?action=showLogin");
- }
- }
-
- /**
- * Expires sessions
- * @return void
- */
- public void run()
- {
- while ( true )
- {
- try
- {
- Thread.sleep (flush);
- Enumeration sessions;
- Session s;
- long expire;
- expire = System.currentTimeMillis();
-
- synchronized (sessionCache)
- {
- sessions = sessionCache.elements();
- }
- while ( sessions.hasMoreElements() )
- {
- s = (Session)sessions.nextElement();
- if ( expire >= s.getExpires() )
- {
- synchronized (sessionCache)
- {
- sessionCache.remove (s.key());
- }
- }
- }
- }
- catch (Exception e)
- {
- return;
- }
- }
- }
-
- }
-
|