kansiho's blog

ruby, python, javascript. Rails, wordpress, OpenCV, heroku...

すごいシンプルなログインなしセッションでのユーザー情報保存機能【rails】自分用メモ

シチュエーション

  • クイズアプリで、わざわざログインさせたくないけど10分間くらいユーザー情報を保存して(次の問いに繋げるといったことをして)いたい。

  • ECサイトのカートに入れる機能

  • ECサイトのお気に入り機能

  • 投票機能で、同一セッションで多重投票されたくない時

実装レベル

重要度の低い情報を扱うとする(個人情報を含まない)

require "cgi"
require "cgi/session"

cgi = CGI.new
session = CGI::Session.new(cgi,{"new_session"=>false})

コマンドラインでオフラインモードで利用するには

hoge.rb(main):001:0> require 'cgi'
=> []
hoge.rb(main):002:0> cgi = CGI.new
(offline mode: enter name=value pairs on standard input)

# 入力を求められる

hoge=123&fuga=456

#さらにCtrl-D を押すことで続きのプログラムが実行される。


#<CGI:0x007fef6b652ce8
 @accept_charset="UTF-8",
 @accept_charset_error_block=nil,
 @cookies={},
 @max_multipart_length=134217728,
 @multipart=false,
 @options={:accept_charset=>"UTF-8", :max_multipart_length=>134217728},
 @output_cookies=nil,
 @output_hidden=nil,
 @params={"hoge"=>["123"], "fuga"=>["456"]}>

# デフォルトでは、一時ファイル領域のテキストファイルで記録される


session = CGI::Session.new(cgi)

=> #<CGI::Session:0x007fef6ce1a4c0
 @dbman=#<CGI::Session::FileStore:0x007fef6ce1a290 @hash={}, @path="/var/folders/g2/4h5d5fms0qg_3chcnw9s3tm00000gq/T/cgi_sid_3b0a42ee87db63bd">,
 @dbprot=[#<CGI::Session::FileStore:0x007fef6ce1a290 @hash={}, @path="/var/folders/g2/4h5d5fms0qg_3chcnw9s3tm00000gq/T/cgi_sid_3b0a42ee87db63bd">],
 @new_session=true,
 @session_id="bea46c8b0b7e8d8cf29f7647251b5f1f">


session.session_id
=> "bea46c8b0b7e8d8cf29f7647251b5f1f"

cookies

Cookieとは、Webサイトの提供者が、Webブラウザを通じて訪問者のコンピュータに一時的にデータを書き込んで保存させる仕組み。

CookieにはWebサイト(Webサーバ)側が指定したデータを保存しておくことができ、利用者の識別や属性に関する情報や、最後にサイトを訪れた日時などを記録しておくことが多い。ネットサービスなどのサイトで利用者のIDなどが保存されると、次にアクセスしたときに自動的に利用者の識別が行われ、前回の続きのようにサービスを受けることができる。 -IT用語辞典

cookies[:hoge] = { :value => "value", :expires => "30.days.from_now", :path => "/store", :domain => "www.example.com", :secure => true }
  • value ブラウザに保存する文字列。文字列のみが格納できる。
  • expiers クッキーの有効期限。設定をしないと、クッキーをメモリ上で管理しブラウザセッション*1が終了すると削除される。
  • path ブラウザがクッキーを送信するパスを設定する
  • domain ブラウザがクッキーを送信するドメインを設定する
  • secure httpsの時だけクッキーを送信するように設定する (追記)

  • httponly trueにすると、IEFireFoxではJavaScriptcookieを取得できなくなる

session

session[:hoge] = "hoge"
# sessionが多重ハッシュになっている場合、
session[:hoge][:fuga]
# => NoMethodError: undefined method `[]' for nil:NilClass

# `try`はこんな感じで書ける
session[:hoge].try(:[], :fuga)

# 削除する
session.delete(:hoge)

session と cookie を整理

ステートレスなHTTPというシステムの下で、URLでuser id を持たせるのは危険である。なぜなら、URLはクライアント側で改変可能であるから。

そこで、サーバーからクライアント側にsession IDだけ渡して、クライアント側に保持してもらう仕組み(クライアント側に保持してもらう仕組みがcookie)が生まれた。クライアント側がサーバー側にsession IDを渡すと、サーバー側は保持していたユーザー情報をsession IDと照らし合わせて提供する。

参考

yachibit.hateblo.jp

blog.willnet.in

d.hatena.ne.jp