Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Railsセッションのしくみ

Railsアプリが、誰がアクセスしているかを認識できなかった場合はどうなりますか?同じ人が2つの異なるページを要求したことを知らなかった場合は?応答を返すとすぐに、保存したすべてのデータが消えた場合はどうなりますか?

これは、ほとんど静的なサイトでは問題ないかもしれません。 ただし、ほとんどのアプリは一部を保存できる必要があります ユーザーに関するデータ。 多分それはユーザーID、または優先言語、あるいは彼らが常にあなたのサイトのデスクトップバージョンを彼らのiPadで見たいかどうかです。

セッション この種のデータを配置するのに最適な場所です。複数のリクエストに対して保持したい少量のデータ。

セッションは使いやすいです:

session[:current_user_id] = @user.id

しかし、それらは少し魔法のようになる可能性があります。セッションとは何ですか? Railsは、適切なデータを適切な人に表示することをどのように知っていますか?また、セッションデータをどこに保存するかをどのように決定しますか?

セッションとは何ですか?

セッションは、1つのリクエスト中にデータを保存し、後のリクエストで読み取ることができる場所です。

コントローラアクションでいくつかのデータを設定できます:

app / controllers / sessions_controller.rb
def create
  # ...
  session[:current_user_id] = @user.id
  # ...
end

そして別の記事で読んでください:

app / controllers / users_controller.rb
def index
  current_user = User.find_by_id(session[:current_user_id])
  # ...
end

見えない それは面白い。ただし、すべてを接続するには、ユーザーのブラウザとRailsアプリの間で調整が必要です。そして、それはすべてクッキーから始まります。

Webページを要求すると、サーバーは応答時にCookieを設定できます:

~ jweiss$ curl -I https://www.google.com | grep Set-Cookie

Set-Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly

ブラウザはそれらのCookieを保存します。 Cookieの有効期限が切れるまで、リクエストを行うたびに、ブラウザはCookieをサーバーに送り返します:

...
> GET / HTTP/1.1
> User-Agent: curl/7.37.1
> Host: www.google.com
> Accept: */*
> Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly
...

多くのクッキーは、ぎこちないように見えます。そして、彼らはそうすることになっています。 Cookie内の情報は、ユーザー向けではないためです。 Railsアプリは、Cookieの意味を理解する役割を果たします。 アプリがそれを設定できるので、アプリはそれを読み取ることができます。

これはセッションと何の関係がありますか?

だから、あなたはクッキーを持っています。 1つのリクエスト中にデータを入力すると、次のリクエストでも同じデータが取得されます。それとセッションの違いは何ですか?

デフォルトでは、Railsでは大きな違いはありません。 RailsはCookieを処理して、Cookieをより安全にします。しかし、それに加えて、それはあなたが期待するように機能します。 RailsアプリはいくつかのデータをCookieに入れ、同じデータがCookieから出てきます。これがすべてだったとしたら、セッションとCookieを区別する理由はありません。

ただし、Cookieがセッションデータの正しい答えであるとは限りません:

  • Cookieに保存できるデータは約4kbのみです。

    これは通常です 十分ですが、そうでない場合もあります。

  • Cookieはリクエストごとに送信されます。

    大きなCookieは、要求と応答が大きくなることを意味します。つまり、Webサイトの速度が低下します。

  • 誤ってsecret_key_baseを公開した場合 、ユーザーはCookie内に入力したデータを変更できます。

    これにcurrent_user_idなどが含まれる場合 、誰でも好きなユーザーになることができます!

  • Cookie内に間違った種類のデータを保存することは安全ではない可能性があります。

注意すれば、これらは大きな問題ではありません。

ただし、次のいずれかの理由でセッションデータをCookie内に保存できない場合、Railsにはセッションを保持する場所が他にもいくつかあります。

代替セッションストア

ないすべてのセッションストア Cookieセッションストアはほぼ同じように機能します。 しかし、実際の例を使用することを考えるのが最も簡単です。

ActiveRecordでセッションを追跡していた場合:

  1. session [:current_user_id] =1を呼び出すと アプリ内にあり、セッションがまだ存在していません:

  2. Railsはセッションに新しいレコードを作成します ランダムなセッションIDを持つテーブル(たとえば、 09497d46978bf6f32265fefb5cc52264

  3. {current_user_id:1}を保存します (Base64でエンコード) data そのレコードの属性。

  4. そして、生成されたセッションID 09497d46978bf6f32265fefb5cc52264を返します。 、 Set-Cookieを使用してブラウザに 。

次にページをリクエストするとき

  1. ブラウザは、 Cookie:を使用して、同じCookieをアプリに送信します ヘッダー。

    (このように: Cookie:_my_app_session =09497d46978bf6f32265fefb5cc52264;
    パス=/; HttpOnly

  2. session [:current_user_id]を呼び出すとき :

  3. アプリはCookieからセッションIDを取得し、そのレコードを sessionsで見つけます。 テーブル。

  4. 次に、 current_user_idを返します。 dataから そのレコードの属性。

データベース、Memcached、Redis、またはその他の場所にセッションを保存する場合でも、ほとんどの場合、セッションはこれと同じプロセスに従います。 Cookieはのみ セッションIDが含まれており、RailsアプリはそのIDを使用してセッションストア内のデータを検索します。

機能する場合は、セッションをCookieに保存するのがはるかに簡単な方法です。 追加のインフラストラクチャやセットアップは必要ありません。

ただし、Cookieセッションストアを超える必要がある場合は、次の2つのオプションがあります。

セッションをデータベースに保存するか、キャッシュに保存します。

セッションをキャッシュに保存する

パーシャルまたはデータをキャッシュするために、すでにMemcacheのようなものを使用している可能性があります。 その場合、キャッシュストアはすでに設定されているため、セッションデータを保存するのに2番目に簡単な場所です。

セッションストアが大きくなりすぎると、古いセッションが自動的にキャッシュから追い出されるため、セッションストアが制御不能になることを心配する必要はありません。また、キャッシュがメモリに保持される可能性が高いため、高速です。

しかし、それは完璧ではありません:

  • 古いセッションを維持することに実際に関心がある場合は、おそらくしたくないでしょう。 それらはキャッシュから追い出されます。

  • あなたのセッションとあなたのキャッシュされたデータはスペースのために戦うでしょう。十分なメモリがない場合は、大量のキャッシュミスや早期期限切れのセッションに直面する可能性があります。

  • キャッシュをリセットする必要がある場合(たとえば、Railsをアップグレードし、古いキャッシュデータが正確でなくなった場合)、全員の有効期限が切れない限り、リセットする方法はありません。 セッション。

それでも、これがセッションデータをAvvoに保存する方法であり、これまでのところうまく機能しています。

データベースへのセッションの保存

セッションデータを合法的に期限切れになるまで保持したい場合は、おそらく何らかのデータベースに保持したいと思うでしょう。 それがRedis、ActiveRecord、またはその他のものであるかどうか。

ただし、データベースセッションストレージにも欠点があります。

  • 一部のデータベースストアでは、セッションが自動的にクリーンアップされません。

    そのため、期限切れのセッションを自分で確認してクリーンアップする必要があります。

  • データベースがセッションデータでいっぱいになったときにデータベースがどのように動作するかを知っておく必要があります。

    セッションストアとしてRedisを使用していますか?すべてのセッションデータをメモリに保持しようとしますか?サーバーにはそのための十分なメモリがありますか、それともスワップを開始するので、 ssh を実行できなくなりますか? それを修正するために?

  • セッションデータを作成するときは、さらに注意する必要があります。そうしないと、データベースが不要なセッションでいっぱいになります。

    たとえば、リクエストごとに誤ってセッションに触れた場合、googlebotは何十万もの役に立たないセッションを作成する可能性があります。そして、それは悪い時期でしょう。

これらの問題のほとんどは非常にまれです。ただし、それでも注意する必要があります。

では、セッションをどのように保存する必要がありますか?

Cookieストアの制限にぶつからないことがかなり確実な場合は、それを使用してください。セットアップはそれほど必要なく、維持するのも面倒ではありません。

キャッシュとデータベースにセッションを保存することは、セッションを早期に期限切れにすることがどれほど悪いかについての判断の呼びかけです。私はセッションデータをかなり一時的なものとして扱っているので、キャッシュストアは私にとってうまく機能します。 通常、私は通常、最初にCookieを試し、次にキャッシュを試し、次にデータベースを試します。

しかし、あなたはどうですか? あなたのをどのように保存しますか セッション?コメントを残して私に知らせてください!

また、RubyとRailsの内部がどのように機能するかについて詳しく知りたい場合は、この記事を参照してください:gemはどのように機能しますか?または、ウェブの仕組みに興味がある場合は、ウェブサーバーとアプリサーバーを確認してください。


  1. データをバックアップするにはどうすればよいですか?

    今日の IT の世界では、包括的なバックアップ戦略を持つことが不可欠です。データが失われる方法は非常に多いため、不快な状況に直面しないためには、データを正常にバックアップする方法を理解することが重要です。では、どのようにデータをバックアップできますか? データ損失 サイバー攻撃、不正な従業員、自然災害、メディアの損傷、および人的エラーは、データを失う可能性があるいくつかの方法にすぎません.データを失うことは、個人にとっては迷惑で悲痛なことかもしれませんが、組織にとっては、その影響は取り返しのつかないものになる可能性があります. Consoltech のこれらの恐ろしい数字のいくつかを以下で見

  2. Android でデータをバインドする方法

    データ バインディングは、視覚的なユーザー入力要素に情報 (データ) を接着するときに使用する手法です。このプロセスでは、入力が更新されるたびに、その背後にあるデータも更新されます。 これは決して新しい概念ではなく、これを設計に組み込んだフレームワークが多数あります (AngularJS/React/Vue など)。 この記事で注目するのは、フロントエンド フレームワークではなく、モバイル開発です。 Google は、Android Jetpack の一部である Data Binding Library を Android に導入しました。 Jetpack ライブラリ スイートに慣れ