现在的位置: 首页 > 综合 > 正文

CAS single-sign-out

2013年10月08日 ⁄ 综合 ⁄ 共 4884字 ⁄ 字号 评论关闭

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 (注释去掉)

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的数据表,表结构及内容如下图:

image

运行rake可能会遇到错误

rake aborted!

No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)

这是因为项目根目录中应该有个Rakefile文件,如果缺少拷一份过来就行了。

     image

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适合我们系统需求所要做的配置和修改。

抱歉!评论已关闭.