What have you found for these years?

2009-05-26

rails 2.3 session 變身

有鑑於 flash 無法送出 cookie, 因此一些 dirty hack 變成必須..
由 javascript 取得 cookie, 塞到 flash 裡,改由 post 至 server.

也就是說,當 flash 的 http post 進來時,rails 的 session
肯定是讀不到東西的,因為沒有 cookie. 這邊就需要 hack 了,
從 post param 中取得 cookie, 接著重製我們的 session instance.

示意程式:

session_key = params['session_key']

這個 session key 就會是我們需要的 cookie,
也是 user identity 最重要的那個「東西」。
只要能取得這個東西,任何人都可以變身成任何人...
這邊講下去就離題了,所以打住。

接著把我們的 rack env(rails 2.3 才有!)取出來:

env = session.instance_variable_get('@env')

因為沒有 reader, 所以只能這樣取,什麼時候會壞掉不知道。
但我覺得 rails 是該提供可以取得 rack env 的東西。
基本上,rack 應該很明顯一定要成為以後的唯一標準,
君不見也有人做 haskell 版?還有 javascript 版。

haskell 版,hack:
http://github.com/nfjinjing/hack/
作者是 nfjinjing, 中國人,可以看看他其他的 repository,
相當厲害。github rebase 也有報導過他的東西。
lambdawan 也有一篇講到他的 haskell blog
http://flolac.iis.sinica.edu.tw/lambdawan/node/69

可惜我沒什麼時間看看他的東西... 他也滿多產的,
常常不時就有新東西。ramaze 作者 manveru 也很早就 follow 他,
可能是因為他也有 fork ramaze.

javascript 版,jack:
http://github.com/gmosx/jack/
這是 server side javascript, 好像也是 apache 的東西,
jack 則是架構在上面的 framework, 被用在 nitro 上:
http://github.com/gmosx/nitro/

nitro 原本是 ruby 的 web framework,
之前一直很看好,但後來就沒維護了。最像的架構是 ramaze,
因此後來我就在看 ramaze 了。但沒想到 nitro 居然,
居然變成 server side javascript 的東西了 @_@
不換個名字嗎?這完全是兩回事了吧......

離題好遠了,總之 rack 是很重要的發明就是了,
概念也被慢慢移植到其他語言與環境上。
rails 在跟隨 rack 上,動作真的有點慢。

回主題,真正的 cookie 變身在這:

env['HTTP_COOKIE'] = env['HTTP_COOKIE'].
gsub(/session_key=([\w\d]+)/, "session_key=#{session_key}")

原本我是寫 .gsub! 但不知道怎麼,好像沒有效果。
只好用他的 writer method, 細節我懶得追究了。
這樣就是把 session key 由原本的值,變成剛剛 post 過來的值。
記得吧?

session_key = params['session_key']

不過這是假設原本就有 session_key, 才可以用 gsub 換掉。
在 flash 的情況下,根本不會有 cookie, 所以可能直接寫進去即可。
例如:

env['HTTP_COOKIE'] = "Cookie: session_key=#{session_key}"
(updated: rack 這邊直接 session_key=xxx 即可,Cookie: 要省掉)

我還沒試 flash, 總之概念是這樣。
接著就是重建 session instance, 不用完全重建,重讀即可:

session.send(:load!)

因為這是 private method, 所以得用 send 繞過去...
執行這個之後,rails 底層會做這件事:

request = Rack::Request.new(env)
sid = request.cookies[@key]

藉此重建新的 session instance, 整個 hash 最後會呼叫:

replace(session)

因此,之後我們就可以用正確(原本)的 session instance 了。
例如原本:

session[:cas_user] # => nil

因為 flash 沒有 cookie. 竄改 cookie 重讀 session 後:

session[:cas_user] # => godfat

以上,休想在 rails 文件裡找到,這些東西他都不會寫的...
想看的話到:

actionpack-2.3.2/lib/action_controller/session/abstract_store.rb

全部都在那。這邊 rails 2.2 時寫得超級混亂.............
2.3 改用 rack 後真的清楚很多。不過 2.2 => 2.3 的
session domain 設定方法又改了,這點實在很討厭...
內部實作修改,甚至結構改變我都沒意見,介面一直改真的讓人想打人。

0 retries:

Post a Comment

All texts are licensed under CC Attribution 3.0