1. ホーム
  2. ruby-on-rails

[解決済み] railsにおけるThread.current[]の安全性について

2023-06-10 08:43:51

質問

に情報を保存することに関して、相反する意見を持ち続けています。 Thread.current ハッシュ (たとえば current_user, current subdomain, など) に情報を保存することに関して、私は相反する意見を持ち続けています。このテクニックは、モデル レイヤー内の後の処理 (クエリ スコープ、監査など) を簡略化する方法として提案されています。

多くの人が、MVCパターンを壊してしまうので、この慣習は受け入れられないと考えています。 他の人々は、アプローチの信頼性/安全性についての懸念を表明しており、私の2部構成の質問は、後者の側面に焦点を当てています。

  1. Thread.current ハッシュは、その全サイクルを通じて、1つのレスポンスに対してのみ利用可能であり、プライベートであることが保証されていますか?

  2. 私は、スレッドが、レスポンスの終わりに、他の入ってくるリクエストに引き渡されるかもしれないことを理解しています。 Thread.current . レスポンスの終了前にそのような情報をクリアすることは可能でしょうか (たとえば Thread.current[:user] = nil をコントローラの after_filter ) を使用すれば、そのようなセキュリティ侵害を防ぐのに十分なのでしょうか?

ありがとうございます。 ジュゼッペ

どのように解決するのですか?

スレッドローカル変数を使用しない特別な理由はありませんが、主な問題点は以下の通りです。

  • スレッドローカル変数を使用するコードをテストするときに、スレッドローカル変数を設定することを覚えなければならないので、テストするのが難しい。
  • スレッドローカルを使用するクラスは、これらのオブジェクトが 利用可能 でなく、スレッドローカル変数の中にあることを知る必要があり、 この種の間接参照は通常 デメテルの法則
  • フレームワークがスレッドを再利用する場合、スレッドローカルをクリーンアップしないことは問題かもしれません (スレッドローカル変数はすでに開始されており、また ||= の呼び出しに依存するコードは失敗するかもしれません。

ということで、全く使えないわけではないものの ベスト アプローチは使用しないことですが、時折、スレッドローカルが非常に多くのコードを変更せずに最も単純な可能な解決策になりそうな壁にぶつかり、妥協して、スレッドローカルの完璧ではないオブジェクト指向モデルを持つか、同じことをするために非常に多くのコードを変更しなければなりません。

もし本当にスレッドローカルの道を進むのであれば、次のような、終了後のクリーンアップを覚えているブロックを使って行うよう、私はきっと助言します。

around_filter :do_with_current_user

def do_with_current_user
    Thread.current[:current_user] = self.current_user
    begin
        yield
    ensure
        Thread.current[:current_user] = nil
    end      
end

これは、このスレッドがリサイクルされる場合に使用される前に、スレッドローカル変数がクリーンアップされることを保証します。