折衷的方式实现php与ruby共享session实现单点登录
2019獨角獸企業重金招聘Python工程師標準>>>
1.背景
前一陣部門要做一個內部討論區,希望能和原有的gitlab集成在一起。
discuz雖然成熟但是感覺不夠高大上,找了幾個ruby的論壇discourse,rabel雖然時髦值夠了但是成熟度又缺了點,最后選了php的question2answer作為論壇程序,采用iframe的方式嵌入原來的gitlab程序。
2.單點登錄方案
2.1.共享cookie
- 在cookie里保存user的信息,php讀cookie并取得用戶信息。
- ruby和php程序要在同一個域名下
- cookie在客戶端是可見的,一般要對cookie進行加密。
- 數據不安全
2.2.共享session
- 在cookie里保存ruby session信息,php獲得session信息后讀session數據。
- ruby和php程序要在同一個域名下
- session內容客戶端不可見。
2.3.cas
- 通過統一認證服務登錄
- ruby和php登錄時重定向至認證服務器,通過驗證后回調相應服務保存token,之后只要具體服務向cas請求token是否過期就可以判斷是否登錄。
由于兩個業務在同一個域名下,這里就放棄了復雜的cas方案;考慮源代碼安全,沒有用cookie存儲用戶信息,最后決定使用共享session的方式實現單點登錄
3.通過session單點登錄
3.1.rails與session
gitlab使用devise作為登錄框架,關于session的配置在config/initilizers/sessions.rb下,默認使用redis方式保存session
Gitlab::Application.config.session_store(:redis_store, # Using the cookie_store would enable session replay attacks.servers: Gitlab::Application.config.cache_store.last, # re-use the Redis config from the Rails cache storekey: '_gitlab_session',secure: Gitlab.config.gitlab.https,httponly: true,path: (Rails.application.config.relative_url_root.nil?) ? '/' : Rails.application.config.relative_url_root)
這里也可以改成在數據庫或者memcached里存儲,存儲格式與redis類似,不多講了。
redis里key為session id,value為序列化后的數據,默認使用的序列化算法為marshal,理論上只要php讀出內容來就可以取得session數據了。
3.2.ruby與序列化
不幸的是,php里沒有能夠直接反序列化marshal對象的的方法。
最初考慮把marshal改為json方式存儲,需要修改redis-store的一些代碼,主要是覆蓋源代碼中的marshal和unmarshal函數,替換為json實現。具體可以參考:Sharing Rails sessions with PHP, ColdFusion, and more!
不過用這個方法出現了一些問題:marshal序列話會保存對象的一些meta信息,json是沒有這些信息的,導致反序列化之后的ruby對象與序列化之前不一樣。
undefined method `sweep' for {"notice"=>"Logged in successfully."}:Hash在網上搜索很久,一個日文的blog提出了解決方案:Rails sessionのシリアライズにJSONが使われない理由: なぜMarshal? JSON/YAMLの罠
主要是在反序列化的時候加了這么一句:
if original.has_key?('flash')original['flash'] = ActionDispatch::Flash::FlashHash.new.update(original['flash']) end
3.3.折衷的方式
這么深度的修改對于這個需求似乎太復雜了,最后還是決定用簡單些的方式,利用ruby開放一個session的json接口,php通過調用接口獲得用戶信息,修改的地方很少:
ruby
class ActiveController < ApplicationControllerdef showrender :json => current_userendend
php
?
轉載于:https://my.oschina.net/u/1189928/blog/806546
總結
以上是生活随笔為你收集整理的折衷的方式实现php与ruby共享session实现单点登录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 30分钟带你熟练性能优化的那点儿事儿(案
- 下一篇: Spring 建立简单的示例