(in-package :araneida) (defclass session () ((name :initarg :name :initform :default :accessor session-name :type symbol :documentation "The name of the session. Allows you to have multiple sessions. Should be a keyword symbol") (slots :initform (make-hash-table) :type hash-table :documentation "The session data") (session-id :initarg :session-id :accessor session-id :type fixnum :documentation "An integer ID for the session") (last-access-time :initarg :last-access-time :accessor last-access-time :type integer :documentation "Universal time of the last time the session was accessed") (lifetime :initarg :lifetime :accessor lifetime :type integer :documentation "How long, in seconds, a session should last. If a session goes beyond its lifetime, it cannot be accessed.") (creation-request :initform nil :initarg :creation-request :type request :accessor creation-request :documentation "Holds a copy of the request that created the session. This will include the headers and body"))) (defvar *session-cookie-name* "X_SESSION" "The cookie name under which Session IDs will be stored. Technically, the cookie will be <*session-cookie-name*>") (defvar *default-session-lifetime* (* 60 15) "Default session lifetime in seconds (default default is 15 minutes)") (defvar *session-id->cookie-value* #'prin1-to-string "Function that converts from the numeric session id into a string to be placed in a cookie If you wanted to do HMAC or some other such system, you could do it by swapping out the functions in *session-id->cookie-value* and *cookie-value->session-id*. For this reason, please note that (funcall *session-id->cookie-value* session-id) may NOT have the same value if called twice. (eql session-id (funcall *cookie-value->session-id* (funcall *session-id->cookie-value* session-id))) should ALWAYS hold true, however") (defvar *cookie-value->session-id* #'parse-integer "Function that takes the string from the session cookie and turns it into the numeric session id See *session-id->cookie-value* for more information") (defvar *request-authorized-for-session-p* (lambda (request session) (declare (ignore request session)) t) "Function that checks to make sure that the request is authorized for the session it claims. Setting this to a different function would allow you to check to see if, for instance, the request-making host is the same now as it was when the session was created. (defun my-sekret-cheker (request session) t) is the default. Possible applications would include checking that the host IP is the same originally as now. See also the documentation for the creation-request slot of session") (defvar *session-table* (make-array 1 :element-type '(or null session) :initial-element nil :adjustable t)) (defun session-p (session) (typep session 'session)) (defun valid-session-p (session) (and (session-p session) (> (+ (lifetime session) (last-access-time session)) (get-universal-time))))