Techioz Blog

Rails 7: 許可されていない認証トークン

概要

私が手伝ってもらうために雇われたプロジェクトで他の人が作った機能にバグを見つけました。これを行ったプログラマは不在で、インターネット上でもこのエラーについて何も見つかりませんでした。そのため、ここで誰かが問題の原因についてアイデアを持っていることを願っています。

関連するモデルは Project と ProjectFilter です。 ProjectFilter はターボ ドロップダウン経由で作成され、(名前が示すように) ユーザーのニーズに応じて既存のプロジェクトをフィルターします。

プロジェクトコントローラー:

def new_filter
  @filter = ProjectFilter.new filter_params
  respond_to do |format|
    format.html { render layout: nil }
  end
end

def create_filter
  index
end

private
 def filter_params
  p = params.permit(:sort_col, :sort_dir, filter: {})
  p.except(:filter).merge(p[:filter])
 end
  
 def filter_and_sort
   @projects_before_filtering = @projects
   filter_projects
   sort_projects
 end

 def filter_projects
   @filter = params[:filter]&.permit(:area_id, :vision, :country_code, :progress) || {}
   @filter.reject! { |_k, v| v.blank? }
   @projects = ProjectFilter.new(@filter).filter(@projects)
 end

これがどのように機能するかを示すスクリーンショットをいくつか示します。

すべてのプロジェクトとドロップダウン

フィルター 1 つ

2つのフィルター

スクリーンショットは現在のリポジトリの前のバージョンのものです (プロジェクトは数か月前に保留され、再開されたとき、会社は古いリポジトリを破棄し、何らかの理由で新しいコピーをアップロードしました)。この古いバージョンでは、この機能は動作します。しかし、新しいものの最初のアップロードにロールバックしても、そうではありません。

両方のリポジトリのコードをチェックしたところ、モデル、コントローラー、ビュー、さらには構成ファイルなど、この機能に関連するどのファイルにもまったく違いがありませんでした。

このような状況を考えると、次のような問題が生じます。

現在のリポジトリでは、この機能を使用しようとすると、発生すべきではない 3 つのことが発生します。

Unpermitted parameters: :authenticity_token, :sort_col, :sort_dir, :filter. 
Context: { controller: ProjectsController, action: create_filter, request: 
#<ActionDispatch::Request:0x00007f944a714130>, params: {"authenticity_token"=>"[FILTERED]",
"sort_col"=>"", "sort_dir"=>"", "filter"=>{"vision"=>"startup", "area_id"=>"",
"country_code"=>"", "progress"=>""}, "controller"=>"projects", "action"=>"create_filter"} }

上記のコントローラーに示されているように、パラメーターが許可されているにもかかわらず。そして、どうすれば真正性トークンが許可されないのでしょうか??自動的に許可されるんじゃないの?

create_filter アクションの index の下にデバッガーを配置すると、次の結果が得られました。

params:
#<ActionController::Parameters {"authenticity_token"=>"[FILTERED]", "sort_col"=>"", 
"sort_dir"=>"", "filter"=>#<ActionController::Parameters {"vision"=>"startup", "area_id"=>"",
 "country_code"=>"", "progress"=>""} permitted: false>, "controller"=>"projects",
 "action"=>"create_filter"} permitted: false>

@filter:
#<ActionController::Parameters {"vision"=>"startup"} permitted: true>

これは、古いリポジトリ内の同じデバッガー クエリの結果とまったく同じです。それでも、この機能は古いものでは機能しますが、新しいものでは機能しません。

すでに確認したこと:

何か確認すべき点はありますか?徹底的につまづくのでロングショットでも大歓迎です。ありがとう!

解決策

これは完全な答えではありませんが、調べられる箇所がいくつかあると思います。

gemfile ファイルと gemfile.lock ファイルを比較します。 Turbolinks や Hotwire で重大なバージョン変更が表示されると思います。

また、JavaScript ファイルを比較すると、ある時点でプロジェクトが Turbolinks から Hotwire の Turbo に切り替わった可能性があるようです。

id=“filter” を持つ HTML 要素だけを使用することはできません。 要素である必要があります。おそらくこれがこの問題の理由です。

そして、それは明らかではありません。なぜなら、このプロジェクトは、通常の HTML 要素に UJS タグを使用する古い Turbolinks から、特殊な DOM 要素を期待する Hotwire の Turbo にアップグレードされたと考えられるからです (Hotwire に詳しくない場合は、Hotwire を確認してください)。

許可されていないパラメータに関しては、@engineersmnky の言うことは完全に正しいです。 #filter_params でパラメータが許可されていることがわかるため、パラメータが許可されていると仮定しています。しかし、それは呼び出されるメソッドではありません。

def filter_and_sort
   @projects_before_filtering = @projects
   filter_projects #<- doesn't permit :authenticity_token, :sort_col, :sort_dir, :filter
   sort_projects #<- not shown in your code
 end

ビューや JS コード、およびコントローラーの残りの部分がなければ、さらにデバッグするのは困難ですが、これが役立つことを願っています。