com.arsdigita.acs
Class ACSSession

java.lang.Object
  |
  +--com.arsdigita.acs.ACSSession

public class ACSSession
extends java.lang.Object

Represents a user session. An ACSSession consists of a user and their session information.

Uses the information stored in the following signed cookies:
cookie value max-age secure
ad_session_id session_id/user_id SessionTimeout no
ad_user_login user_id never expires no
ad_user_login_secure user_id/random never expires yes
ad_secure_token session_id/user_id/random SessionLifetime yes
the random data is used to hinder attack the secure hash. currently the random data is System.currentTimeMillis()/1000

Secure cookies not implemented yet, but intended for use with HTTPS

A "signed" cookie is of the format "{data} secret_token_id expire_time hash", where hash = SHA1(data || secret_token_id || expire_time || secrets[secret_token_id]); secrets is a map (id -> secret token).


Field Summary
static java.lang.String cvsId
           
 
Constructor Summary
ACSSession(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp)
          Constructs a connection object out of a servlet request and servlet response.
 
Method Summary
 void assignSessionId()
           
 void assignSessionId(java.lang.String sessionId)
          Sets up the session, setting the instance variables and issuing a cookie if necessary.
static ACSSession get()
           
 java.lang.String getClientProperty(java.lang.String name, java.lang.String value)
          Equivalent of getClientProperty("", name, value)
 java.lang.String getClientProperty(java.lang.String def, java.lang.String module, java.lang.String name)
          Looks up a property for the current session.
 java.math.BigDecimal getSessionId()
          Returns the session id of the currently connecting browser.
 java.math.BigDecimal getUserId()
          Returns the currently-logged-in user (or null), validating it first
 boolean isSecure()
          Returns true if the user connected via HTTPS.
 java.math.BigDecimal maybeRedirectForRegistration()
          Checks to see if a user is logged in.
 void renewCookies()
          Renews the ad_session_id and ad_secure_token cookies so they don't expire.
static void set(ACSSession session)
           
 void setClientProperty(boolean isSecure, java.lang.String module, java.lang.String name, java.lang.String value)
          Sets a client (session-level) property.
 void setCookie(java.lang.String name, java.lang.String value)
          Sets a non-persistent cookie in the response, on the root path.
 void setCookie(java.lang.String name, java.lang.String value, java.lang.String path)
          Sets a non-persistent cookie in the response, on the specified path.
 void setCookie(java.lang.String name, java.lang.String value, java.lang.String path, int maxAge)
          same as setCookie(String name, String value, String path, int maxAge, false)
 void setCookie(java.lang.String name, java.lang.String value, java.lang.String path, int maxAge, boolean isSecure)
          Sets a cookie in the response, on the specified path.
 void setSignedCookie(java.lang.String name, java.lang.String value, java.lang.String path, int maxAge)
          Same as setSignedCookie(name, value, path, maxAge, false);
 void setSignedCookie(java.lang.String name, java.lang.String value, java.lang.String path, int maxAge, boolean isSecure)
          Sets a "signed" cookie.
 void userLogin(java.math.BigDecimal userId, boolean forever)
          Logs the user in, forever (via the ad_user_login cookie) if forever is true.
 void userLogout()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

cvsId

public static final java.lang.String cvsId
Constructor Detail

ACSSession

public ACSSession(javax.servlet.http.HttpServletRequest req,
                  javax.servlet.http.HttpServletResponse resp)
           throws java.sql.SQLException,
                  com.arsdigita.acs.InvalidSessionException
Constructs a connection object out of a servlet request and servlet response.
Throws:
com.arsdigita.acs.InvalidSessionException - thrown when invalid secure cookies forces redirection for registration
java.sql.SQLException - thrown on database error
Method Detail

get

public static ACSSession get()

set

public static void set(ACSSession session)

getSessionId

public java.math.BigDecimal getSessionId()
Returns the session id of the currently connecting browser.

getUserId

public java.math.BigDecimal getUserId()
Returns the currently-logged-in user (or null), validating it first

isSecure

public boolean isSecure()
Returns true if the user connected via HTTPS.
Returns:
Returns true if the user connected via HTTPS.

renewCookies

public void renewCookies()
Renews the ad_session_id and ad_secure_token cookies so they don't expire.

assignSessionId

public void assignSessionId()
                     throws java.sql.SQLException

assignSessionId

public void assignSessionId(java.lang.String sessionId)
                     throws java.sql.SQLException
Sets up the session, setting the instance variables and issuing a cookie if necessary.

userLogin

public void userLogin(java.math.BigDecimal userId,
                      boolean forever)
               throws java.sql.SQLException
Logs the user in, forever (via the ad_user_login cookie) if forever is true. Or logs the user out by hosing the ad_user_login_cookie if userId is null.
Parameters:
userId - The user ID for the user that we're logging in or null if we are logging out.
forever - If true, generate a ad_user_login cookie.

userLogout

public void userLogout()

maybeRedirectForRegistration

public java.math.BigDecimal maybeRedirectForRegistration()
                                                  throws RedirectException,
                                                         java.sql.SQLException
Checks to see if a user is logged in. If not, redirects to /register/index to require the user to register. When registration is complete, the user will return to the current location. All variables in the form (both posts and gets) will be maintained. Note that this will return out of its caller so that the caller need not explicitly call "return".
Returns:
the user id if login was succesful.
Throws:
RedirectException - to force the calling page to terminate

setClientProperty

public void setClientProperty(boolean isSecure,
                              java.lang.String module,
                              java.lang.String name,
                              java.lang.String value)
                       throws java.sql.SQLException
Sets a client (session-level) property.
Parameters:
secure - if true, the property will not be retrievable except via a validated, secure (HTTPS) connection.
module - the module for which the property is being set
name - the name of the property
value - the value to set

getClientProperty

public java.lang.String getClientProperty(java.lang.String def,
                                          java.lang.String module,
                                          java.lang.String name)
                                   throws java.sql.SQLException
Looks up a property for the current session. If the property is secure, we must be on a validated session over SSL.
Parameters:
def - the default value to return
module - the module the property belongs to
name - the name of the property
Returns:
the value of the property, or def if not defined; or empty string if secure property requested over insecure connection.

getClientProperty

public java.lang.String getClientProperty(java.lang.String name,
                                          java.lang.String value)
                                   throws java.sql.SQLException
Equivalent of getClientProperty("", name, value)

setCookie

public void setCookie(java.lang.String name,
                      java.lang.String value)
Sets a non-persistent cookie in the response, on the root path.
Parameters:
name - the name of the cookie
value - the cookie value

setCookie

public void setCookie(java.lang.String name,
                      java.lang.String value,
                      java.lang.String path)
Sets a non-persistent cookie in the response, on the specified path.
Parameters:
name - the name of the cookie
value - the cookie value
path - the cookie path

setCookie

public void setCookie(java.lang.String name,
                      java.lang.String value,
                      java.lang.String path,
                      int maxAge)
same as setCookie(String name, String value, String path, int maxAge, false)

setCookie

public void setCookie(java.lang.String name,
                      java.lang.String value,
                      java.lang.String path,
                      int maxAge,
                      boolean isSecure)
Sets a cookie in the response, on the specified path.
Parameters:
name - the name of the cookie
value - the cookie value
path - the cookie path
maxAge - the lifetime for the cookie. If maxAge is 0, removes the cookie from the client. If maxAge is -1, cookie will be non-persistent (only lasts until client quits their browser).
isSecure - if isSecure is true, cookie will only go over SSL connections

setSignedCookie

public void setSignedCookie(java.lang.String name,
                            java.lang.String value,
                            java.lang.String path,
                            int maxAge,
                            boolean isSecure)
Sets a "signed" cookie. The actual cookie data sent back with the response includes a secure hash (SHA1) of the value concatenated with a secret token, and a key to the secret token on the server. The cookie is later verified by looking up the correct secret token and verifying the hash against the hash presented by the browser.

"Signed" is in quotes because it is somewhat of a misnomer. Signed cookies are not signed in the strict sense, since the user can't verify that the cookie is really from our server. Perhaps "certified" would be a better word.

The actual cookie data is set in the format: {value} token_id expire_time hash where hash is sha1(value || token_id || expire_time || tokens[token_id])

A cut-and-paste attack against the system (i.e., changing the value or its expiration time and calculating a new valid hash) would either require SHA1 being insecure, or knowing a secret token-id mapping. For the latter, the hacker has needs shell and/or database access to the server.

Parameters:
name - cookie name
value - cookie value
path - the path for which the cookie applies; should usually be '/' (whole site)
maxAge - the max age of the cookie in seconds; 0 means hose the cookie and -1 means only last for the browser session
isSecure - if isSecure is true, only send cookie over HTTPS connection

setSignedCookie

public void setSignedCookie(java.lang.String name,
                            java.lang.String value,
                            java.lang.String path,
                            int maxAge)
Same as setSignedCookie(name, value, path, maxAge, false);