CAS退出登录时会记住上次退出的是哪个系统,当下次你用不同的账户登录时还是会进入那个系统。我们希望每次都走管理服务器,由它根据用户账户的区域来决定跳转到哪里。测试发现,先用nanjingView登录到采集服务器,由于是第一次登录,当然是先登到管理服务器再跳转到采集服务器,于是管理服务器和采集服务器上都有用户登录的session信息,从采集服务器退出后,会删除采集服务器上的登录信息,但是管理服务器上的信息还保存着。再次用root进行登录时,(去掉了destination后),会先到管理服务器,这时发现有用户的session存在,它不会用新的用户信息重新写session,还是用以前的信息,于是我们session[:cas_user]取出来的还是nanjingView,然后这个账户是市级,当然就跳转到采集服务器了,但是到采集服务器后得到的用户信息就会是root的信息,因为这些信息是cas server端过来的,并不是从管理服务器来的。这就解释了为什么没有了destination还是一直会跳转到采集服务器。并不是哪里保存了上次退出登录的地址,就是因为管理服务器一直保存着nanjingView用户的信息。想要解决这个问题,只能退出采集服务器时,也要删除管理服务器上的登录信息。于是就讲到了下面的Sigle-sign-out。
配置Single-sign-out:
- server端配置文件config.yml
##### SINGLE SIGN-OUT ########################################################## # When a user logs in to a CAS-enabled client application, that application # generally opens its own local user session. When the user then logs out # through the CAS server, each of the CAS-enabled client applications need # to be notified so that they can close their own local sessions for that user. # # Up until recently this was not possible within CAS. However, a method for # performing this notification was recently added to the protocol (in CAS 3.1). # This works exactly as described above -- when the user logs out, the CAS # server individually contacts each client service and notifies it of the # logout. Currently not all client applications support this, so this # behaviour is disabled by default. To enable it, uncomment the following # configuration line. Note that currently it is not possible to enable # or disable single-sign-out on a per-service basis, but this functionality # is planned for a future release. #enable_single_sign_out: true
将enabel_single_sign_out置为true (注释去掉)
- client端 (参看http://github.com/gunark/rubycas-client)
1. 项目environment.rb文件添加如下配置:
CASClient::Frameworks::Rails::Filter.configure(
:cas_base_url => "https://cas.example.foo/",:enable_single_sign_out => true
)
2. /config/initializers中session_store.rb文件修改如下:
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information# (create the session table with "rake db:sessions:create")
ActionController::Base.session_store = :active_record_store
(去掉最后一行注释,Single-sign-out要求sesison存储用ActiveRecord方式,默认是用 cookie_session方式)
之前在网上看到修改的方式都是这样的 config.action_controller.session_store = :active_record_store ,然后就去environment.rb文件中去改,改完会报错。应该是因为Rails版本升级了,现在需要在session_store.rb文件中修改。
3. 创建session数据表
在项目的根目录下运行 rake db:sessions:create
会在项目db文件夹下生成migrate文件夹,并在其中生成文件 20100507031926_create_sessions.rb,该文件内容如下:
class CreateSessions def self.up create_table :session do |t| t.string :session_id, :null => false t.text :data t.timestamps end add_index :session, :session_id add_index :session, :updated_at end def self.down drop_table :session end end
接着运行命令 rake db:migrate
此时会在项目配置的数据库中生成名为session的数据表,表结构及内容如下图:
运行rake可能会遇到错误
rake aborted!
No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)
这是因为项目根目录中应该有个Rakefile文件,如果缺少拷一份过来就行了。
4. 去掉外键保护
如果设置了外键保护,会遇到错误 ActionController::InvalidAuthenticityToken
解决方法:在 application_controller.rb文件将不能有外键保护的方法except
protect_from_forgery(:except =>[:login,:logoutcas,:logout,:filter,:single_sign_out])skip_before_filter :verify_authenticity_token
或者修改配置文件config/environments/development.rb# Disable request forgery protection in development environment
config.action_controller.allow_forgery_protection = false
不过这样会造成所有的外键保护都不能用,建议使用第一种方法。
这里的解决方法是参考文章 http://www.javaeye.com/topic/350718
登出系统后去掉destination的方法:
登出某个系统后,url会带有?destination参数指向登出的系统,下次登录时就会进入该系统,该功能是通过客户端vendor/plugins/rubycas-client/lib/casclient/frameworks/rails中的filter.rb文件中实现:
# Clears the given controller's local Rails session, does some local # CAS cleanup, and redirects to the CAS logout page. Additionally, the # request.referer value from the controller instance # is passed to the CAS server as a 'destination' parameter. This # allows RubyCAS server to provide a follow-up login page allowing # the user to log back in to the service they just logged out from # using a different username and password. Other CAS server # implemenations may use this 'destination' parameter in different # ways. # If given, the optional service URL overrides # request.referer. def logout(controller, service = nil) referer = service || controller.request.referer st = controller.session[:cas_last_valid_ticket] delete_service_session_lookup(st) if st controller.send(:reset_session) controller.send(:redirect_to, client.logout_url(referer)) end
在这里将referer赋值为nil,或者可以在客户端用来logout的方法中进行处理,方法如下:
比方我们自己写了logout_controller.rb文件:
class LogoutController def logoutcas self.request.env['HTTP_REFERER']=nil CASClient::Frameworks::Rails::Filter.logout(self) end end
用 self.request.env['HTTP_REFERER']=nil 也可以将http的referer信息清空。
当然你去除了destination参数之后,要在cas服务端的/lib/ruby/gems/1.8/gems/rubycas-server-0.7.999999.20100202/lib/casserver中controllers.rb文件的
Logout类的get方法中把@service赋值:@service = http://192.168.1.84:4000/redirect/redirect,不然casserver验证登录后不知道要跳转到哪里,会就留在登录页面(只告知你登录成功了~)
登录管理服务器根据用户账户跳转:
另一个我们对controllers.rb文件做的修改是,在Login类的get方法中修改@service,
if @service.nil? or @service==""
@service = "http://192.168.1.84:4000/redirect/redirect"
end
只在@service没有值的情况下强制跳转到redirect方法。
总结
以上就是为了让CAS适合我们系统需求所要做的配置和修改。