Jpmobileのtrans_sid

jpmobileのREADME

=== セッションIDの付与(Transit SID)
==== Cookie非対応携帯だけに付与する
class MyController
trans_sid
end

==== PCにも付与する
class MyController
trans_sid :always
end

PC向けのWebアプリをやってると縁がありませんが
cookieに対応していない携帯のブラウザ向けに
セッション管理をするためにURLとPOSTデータにセッションIDを引き回すことでセッション管理をする。
その機能をTransit SIDということで


jpmobile/lib/jpmobile/trans_sid.rb

module ActionController
  class CgiRequest
    alias_method :initialize_without_ext, :initialize
    def initialize(cgi, options = {}) 
      initialize_without_ext(cgi, options)
      ENV['QUERY_STRING'] = query_string
    end 
  end 
end

class ActionController::Base #:nodoc:
  class_inheritable_accessor :trans_sid_mode
  alias :transit_sid_mode :trans_sid_mode
  class << self
    def trans_sid(mode=:mobile)
      include Jpmobile::TransSid
      self.trans_sid_mode = mode
      unless mode == :none
        # CSRF対策への対策
        session :cookie_only => false
        # url/postからsession_keyを取得できるようhookを追加する
        unless ::CGI::Session.private_method_defined?(:initialize_without_session_key_fixation)
          ::CGI::Session.class_eval do
            alias_method :initialize_without_session_key_fixation, :initialize
            def initialize(cgi, options = {}) 
              key = options['session_key']
              if cgi.cookies[key].empty?
                session_id = (CGI.parse(cgi.env_table['RAW_POST_DATA'])[key] rescue nil) ||
                  (CGI.parse(ENV['QUERY_STRING'] || cgi.query_string)[key] rescue nil)
                cgi.params[key] = session_id unless session_id.blank?
              end
              initialize_without_session_key_fixation(cgi, options)
            end
          end
        end
      end 
    end 
    alias :transit_sid :trans_sid
  end 
end


CgiRequestのinitializeを拡張しているのは、コメントにあるとおり

# FastCGI環境では(どういうわけか) cgi.query_string でクエリ文字列を取得できないので
# ENV['QUERY_STRING'] に代入しておく。

ということらしいです。


ActionController::Baseに追加するクラスメソッドtrans_sidは

  • Jpmobile::TransSidモジュールをインクルード
    • コントローラーの処理後にURLのケツにセッションIDをくっつけたり、フォームがあるときはセッションIDをhiddenで追加したりしてくれます
  • Transit SIDを有効にするなら
session :cookie_only => false

でセッション管理cookie限定を解除してます
ここのsessionはsessionクラスメソッドですね・・
セッションの制御の仕方について


Railsのデフォルトは:cookie_only => trueっすね
セキュリティ対策が打たれているけど、それを解除するんで

 # CSRF対策への対策

ということですか。
第3回:Railsでセッションハイジャックを実体験


session_keyはconfig/environment.rbなどで指定したキー値
クライアントからcookieが送られてこなかったらPOSTデータやQUERY_STRING環境変数やクエリストリングを漁ってsession_keyを探し出してcgi.paramsに入れてやるぜえ!というところでしょうか。