Permalink
Browse files

add active record ticket store

  • Loading branch information...
1 parent 1b26426 commit 47d31d6a09f94183e8e85c2c954abb37c7d97084 @soupmatt soupmatt committed Jun 15, 2011
View
1 lib/casclient/client.rb
@@ -40,6 +40,7 @@ def configure(conf)
@log = CASClient::LoggerWrapper.new
@log.set_real_logger(conf[:logger]) if conf[:logger]
+ @ticket_store.log = @log
@conf_options = conf
end
View
37 lib/casclient/frameworks/rails/filter.rb
@@ -78,8 +78,7 @@ def filter(controller)
controller.session[:casfilteruser] = vr.user
if config[:enable_single_sign_out]
- f = @@client.ticket_store.store_service_session_lookup(st, controller.request.session_options[:id] || controller.session.session_id)
- log.debug("Wrote service session lookup file to #{f.inspect} with session id #{controller.request.session_options[:id] || controller.session.session_id.inspect}.")
+ @@client.ticket_store.store_service_session_lookup(st, controller)
end
end
@@ -218,7 +217,7 @@ def login_to_service(controller, credentials, return_path)
def logout(controller, service = nil)
referer = service || controller.request.referer
st = controller.session[:cas_last_valid_ticket]
- @@client.ticket_store.delete_service_session_lookup(st) if st
+ @@client.ticket_store.cleanup_service_session_lookup(st) if st
controller.send(:reset_session)
controller.send(:redirect_to, client.logout_url(referer))
end
@@ -297,38 +296,8 @@ def single_sign_out(controller)
end
log.debug "Intercepted single-sign-out request for CAS session #{si.inspect}."
-
- begin
- required_sess_store = ActiveRecord::SessionStore
- current_sess_store = ActionController::Base.session_store
- rescue NameError
- # for older versions of Rails (prior to 2.3)
- required_sess_store = CGI::Session::ActiveRecordStore
- current_sess_store = ActionController::Base.session_options[:database_manager]
- end
-
- if current_sess_store == required_sess_store
- session_id = @@client.ticket_store.read_service_session_lookup(si)
-
- if session_id
- session = current_sess_store::Session.find_by_session_id(session_id)
- if session
- session.destroy
- log.debug("Destroyed #{session.inspect} for session #{session_id.inspect} corresponding to service ticket #{si.inspect}.")
- else
- log.debug("Data for session #{session_id.inspect} was not found. It may have already been cleared by a local CAS logout request.")
- end
-
- log.info("Single-sign-out for session #{session_id.inspect} completed successfuly.")
- else
- log.warn("Couldn't destroy session with SessionIndex #{si} because no corresponding session id could be looked up.")
- end
- else
- log.error "Cannot process logout request because this Rails application's session store is "+
- " #{current_sess_store.name.inspect}. Single Sign-Out only works with the "+
- " #{required_sess_store.name.inspect} session store."
- end
+ @@client.ticket_store.process_single_sign_out(si)
# Return true to indicate that a single-sign-out request was detected
# and that further processing of the request is unnecessary.
View
48 lib/casclient/tickets/storage.rb
@@ -2,15 +2,42 @@ module CASClient
module Tickets
module Storage
class AbstractTicketStore
- def store_service_session_lookup(st, sid)
- raise 'Implement this in a subclass!'
+
+ attr_accessor :log
+ @log = CASClient::LoggerWrapper.new
+
+ def process_single_sign_out(si)
+
+ session_id, session = get_session_for_service_ticket(si)
+ if session
+ session.destroy
+ log.debug("Destroyed #{session.inspect} for session #{session_id.inspect} corresponding to service ticket #{si.inspect}.")
+ else
+ log.debug("Data for session #{session_id.inspect} was not found. It may have already been cleared by a local CAS logout request.")
+ end
+
+ if session_id
+ log.info("Single-sign-out for service ticket #{session_id.inspect} completed successfuly.")
+ else
+ log.debug("No session id found for CAS ticket #{si}")
+ end
end
- def read_servcie_session_lookup(st)
+ def get_session_for_service_ticket(st)
+ session_id = read_service_session_lookup(si)
+ if session_id
+ session = ActiveRecord::SessionStore::Session.find_by_session_id(session_id)
+ else
+ log.warn("Couldn't destroy session with SessionIndex #{si} because no corresponding session id could be looked up.")
+ end
+ session_id, session
+ end
+
+ def store_service_session_lookup(st, controller)
raise 'Implement this in a subclass!'
end
- def delete_service_session_lookup(st)
+ def cleanup_service_session_lookup(st)
raise 'Implement this in a subclass!'
end
@@ -21,6 +48,11 @@ def save_pgt_iou(pgt_iou, pgt)
def retrieve_pgt(pgt_iou)
raise 'Implement this in a subclass!'
end
+
+ protected
+ def read_service_session_lookup(st)
+ raise 'Implement this in a subclass!'
+ end
end
# A Ticket Store that keeps it's tickets in a directory on the local filesystem.
@@ -49,9 +81,11 @@ def initialize(config={})
# cas_sess.<session ticket> and its text contents is the corresponding
# Rails session id.
# Returns the filename of the lookup file created.
- def store_service_session_lookup(st, sid)
+ def store_service_session_lookup(st, controller)
raise CASException, "No service_ticket specified." unless st
- raise CASException, "No session_id specified." unless sid
+ raise CASException, "No controller specified." unless controller
+
+ sid = controller.request.session_options[:id] || controller.session.session_id
st = st.ticket if st.kind_of? ServiceTicket
f = File.new(filename_of_service_session_lookup(st), 'w')
@@ -77,7 +111,7 @@ def read_service_session_lookup(st)
# closed.
#
# See #store_service_session_lookup.
- def delete_service_session_lookup(st)
+ def cleanup_service_session_lookup(st)
raise CASException, "No service_ticket specified." unless st
st = st.ticket if st.kind_of? ServiceTicket
View
67 lib/casclient/tickets/storage/active_record_ticket_store.rb
@@ -0,0 +1,67 @@
+#require 'active_record'
+
+module CASClient
+ module Tickets
+ module Storage
+
+ # A Ticket Store that keeps it's ticket in database tables using ActiveRecord.
+ #
+ # Services Tickets are stored in an extra column add to the ActiveRecord sessions table.
+ # Proxy Granting Tickets and their IOUs are stored in the cas_pgtious table.
+ #
+ # This ticket store takes the following config parameters
+ # :pgtious_table_name - the name of the table
+ class ActiveRecordTicketStore < AbstractTicketStore
+
+ def initialize(config={})
+ config ||= {}
+ if config[:pgtious_table_name]
+ CasPgtiou.set_table_name = config[:pgtious_table_name]
+ end
+ end
+
+ def store_service_session_lookup(st, controller)
+ #get the session from the rack env using ActiveRecord::SessionStore::SESSION_RECORD_KEY = 'rack.session.record'
+
+ st = st.ticket if st.kind_of? ServiceTicket
+ session = controller.request.env[ActiveRecord::SessionStore::SESSION_RECORD_KEY]
+ session.service_ticket = st
+ end
+
+ def get_session_for_service_ticket(st)
+ st = st.ticket if st.kind_of? ServiceTicket
+ ActiveRecord::SessionStore::Session.find_by_service_ticket(st)
+ end
+
+ def cleanup_service_session_lookup(st)
+ #no cleanup needed for this ticket store
+ end
+
+ def save_pgt_iou(pgt_iou, pgt)
+ pgtiou = CasPgtiou.create(:pgt_iou => pgt_iou, :pgt_id => pgt)
+ end
+
+ def retrieve_pgt(pgt_iou)
+ raise CASException, "No pgt_iou specified. Cannot retrieve the pgt." unless pgt_iou
+
+ pgtiou = CasPgtiou.find_by_pgt_iou(pgt_iou)
+ pgt = pgtiou.pgt_id
+
+ raise CASException, "Invalid pgt_iou specified. Perhaps this pgt has already been retrieved?" unless pgt
+
+ pgtiou.destroy
+
+ pgt
+
+ end
+
+ end
+
+ class CasPgtiou < ActiveRecord::Base
+ #t.string :pgt_iou, :null => false
+ #t.string :pgt_id, :null => false
+ #t.timestamps
+ end
+ end
+ end
+end
View
4 rails_generators/active_record_ticket_store/active_record_ticket_store_generator.rb
@@ -14,6 +14,10 @@ def manifest
end
protected
+ def banner
+ "Usage: #{$0} #{spec.name} [CreateActiveRecordTicketStore] [options]"
+ end
+
def default_session_table_name
ActiveRecord::Base.pluralize_table_names ? 'session'.pluralize : 'session'
end

0 comments on commit 47d31d6

Please sign in to comment.