11

Rack が提供するセッション管理ミドルウェアはすべて、ユーザーを識別するための Cookie に基づいています。私は API を開発しているので、セッション ID をクエリ文字列パラメーターとして明示的に渡したいと思います。コード ベースを見ると、すべてのセッション ミドルウェアが Cookie の読み取り/書き込みを行う共通のクラスから拡張されているため、このユース ケースが考慮されていないようです。

だから私の質問は - クッキーストアではなく、クエリ文字列でセッションIDを維持できるようにする、代替ラックミドルウェアまたはラック組み込みミドルウェアのモンキーパッチを維持するプロジェクトはありますか?

4

2 に答える 2

9

Rack は、Cookie の代わりにカスタム セッション ID アイテムを使用できます。

require 'rack/session/abstract/id'

ラックのドキュメントは、検索を開始するのに役立つ場合があります。「スキップ」オプション(または「延期」オプション)を探していると思います。

ドキュメント:

ID は、ID ベースのセッション サービスを実装するための基本的なフレームワークをセットアップします。セッションを維持するためにクライアントに送信される Cookie には、ID 参照のみが含まれます。上書きする必要があるのは #get_session と #set_session だけです。

すべてのパラメーターはオプションです。

  • :key は Cookie の名前を決定します。デフォルトでは「rack.session」です。
  • :path、:domain、:expire_after、:secure、および :httponly は、Rack::Response#add_cookie によって関連する Cookie オプションを設定します
  • :skip は、応答に Cookie を設定したり、セッション状態を更新したりしません
  • :defer は応答に Cookie を設定しませんが、バックエンドで使用されている場合はセッション状態を更新します
  • :renew (実装に依存) は、新しいセッション ID の生成と、新しい ID で参照されるデータの移行を促します。:defer が設定されている場合、オーバーライドされ、Cookie が設定されます。
  • :sidbits は、生成されたセッション ID の長さのビット数を設定します。

これらのオプションは、env['rack.session.options'] の場所で、リクエストごとに設定できます。さらに、セッションの ID は、キー :id のオプション ハッシュ内にあります。その値を変更することは強くお勧めしません。

Rack::Utils::Context と互換性があります。

デフォルトでは含まれていません。使用するには「rack/session/abstract/id」が必要です。

ソース:

  class ID
    DEFAULT_OPTIONS = {
      :key =>           'rack.session',
      :path =>          '/',
      :domain =>        nil,
      :expire_after =>  nil,
      :secure =>        false,
      :httponly =>      true,
      :defer =>         false,
      :renew =>         false,
      :sidbits =>       128,
      :cookie_only =>   true,
      :secure_random => (::SecureRandom rescue false)
    }

これが手がかりになることを願っています...詳細がわかりましたら、ここで結果を共有できますか?

編集:

手品は、オプション:cookie_only => falseとを組み合わせること:defer => trueです。もちろん、標準の Rack::Session::Cookie はここではあまり意味がないので、次のようにすることもできます。

use Rack::Session::Pool, :cookie_only => false, :defer => true

興味深いことに、実行時にオプションを変更できます。私のユースケースでは、明示的なパラメーター受け渡しスタイルと一緒に従来の Cookie ベースのメカニズムを実際にサポートする必要があるため、次のことを行いました。

class WebApp < Sinatra::Base

  configure do
    use Rack::Session::Pool, :key => 'session_id'
  end

  before do
    # Switch to parameter based session management if the client is an ios device
    if env['HTTP_USER_AGENT'] =~ /iOS/
      session.options[:cookie_only] = false
      session.options[:defer] = true
    end
  end

  get '/' do
    session[:user_id] ||= nil # This triggers a session-write, giving us a valid session-id
    body "session_id=#{session.id}"
  end
end
于 2013-03-19T13:50:46.723 に答える
3

API アプリケーションでの Cookie の使用をなくしたいが、セッションを管理したい場合。たとえば、私の場合、セッション識別子はトークンから来ました。extract_session_id受信したトークンからセッション識別子を抽出するには、メソッドを再定義する必要があります。Rack::Session::Abstract::IDこのメソッドは、Cookie に基づいてデフォルトの実装を提供するため、セッション ストア クラスで再定義する必要があります。通常はインスタンスで表されるセッションオブジェクトのRack::Session::Abstract::ID#current_session_idメソッドを呼び出すメソッドから呼び出されます。そして、セッションストアからのこのメソッド内で、最終的に呼び出されました。#idRack::Session::Abstract::SessionHashSessionHash#id#extract_session_id

セッション識別子エクストラクタを個別に構成する方が簡単だと思いますが、セッション識別子をセッションデータとともに Cookie に保存したいという願望は、そのだまされた設計につながります。

同様に、メソッドとのRack::Session::Abstract::IDクラスでCookie の相互作用が見られるのは少し奇妙です。したがって、Cookie が設定されないことを完全に確認するには、ストアでもメソッドを再定義できます。ここの回答の1つで述べたように、セッションストレージミドルウェアを設定することでおそらく同じ目標を達成できますが、私はこれを確認していません。#commit_session#set_cookie#set_cookiecookie_only: false, defer: true

ミドルウェア スタックを変更して、Cookie とやり取りするすべてのミドルウェアと、おそらくブラウザー固有のミドルウェアを除外する必要があります。Rails のデフォルトのミドルウェア スタックでは、次のようになります。

# config/application.rb
[
  Rack::MethodOverride, # browser specific
  ActionDispatch::Cookies,
  ActionDispatch::Flash
].each do |middleware|
  config.middleware.delete(middleware)
end

同様に、セッション ストアをサーバー側に情報を保存するもの (redis など) に置き換える必要があります。たとえば、次のようになります。

# config/initializers/session_store.rb
Rails.application.config.session_store ::Custom::Session::TokenRedisStore

私の場合、上記のすべてのメソッド ::Custom::Session::TokenRedisStoreを継承して再定義しました。宝石に含まれています。したがって、使用する場合は、明らかにそれを追加する必要があります。::RedisSessionStore::RedisSessionStoreredis-session-storeGemfile

私はRails 4.2.xでそれを行いますが、Rackどこでも同じように、同じアプローチをどのフレームワークにも採用できます。

于 2015-02-17T11:22:22.973 に答える