勝手に編集や削除をされないよう、コントローラーでアクセス制御をつける方法を解説しています。
概要
- 投稿したユーザー以外、編集や削除ができないようにコントローラーで設定
- 使用するのはユーザー登録、テキスト投稿だけの超簡易アプリ
git clone してお手元で試せるよう、Githubで公開しています。
別のユーザーの投稿を編集できてしまう
ユーザーを2人作成
1@1、2@2という2人のユーザーを作成しました。
文章の投稿
それぞれ1つずつ投稿を行いました。
編集ボタンの制御
投稿者自身がログインしている場合のみ、編集ボタンが表示されるようにします。
ただし、以下のようなURLを直接打ち込むことで、編集画面に遷移できてしまいます。
http://localhost:3000/posts/編集対象のpostのid/edit
コントローラーでアクセス制御
コントローラーにて、投稿者以外は編集できないように2つメソッドを追加します。
1.authenticate_user!
こちらを使うことで、「ログインしていない場合はログイン画面に遷移させる」という挙動を実装できます。
before_action :authenticate_user!,except: [:index]
2.「投稿者でない場合はトップページに遷移する」
次に、「投稿者でない場合はトップページに遷移する」というメソッドを定義します。
editに適用することで、直接URLを入力してもトップページに遷移するようにできました。
class PostsController < ApplicationController before_action :authenticate_user!,except: [:index] before_action :set_post,except:[:index,:new,:create] before_action :user_check,only:[:edit] (省略) def user_check if current_user != @post.user redirect_to root_path end end end
user_checkにて、「現在のユーザーと投稿したユーザーが不一致の場合、トップページに遷移する」という挙動を実装しています。
(user_checkより前にauthenticate_user!が呼び出されるため、current_user!というメソッドが使用できます。)
editへのアクセス制御だけでは不十分
updateには適用しなくても良いのでしょうか?
実は、適用する必要があります。
Chromeの検証を使用し、データを書き換えることができてしまうのです。
検証画面を使ってみましょう。
右クリックでEdit as HTMLを選択し、body内にフォームを作成します。
すると、トップページに編集用のフォームを作ることができてしまいます。
このフォームを使用すると、投稿者以外でも情報を書き換えることができてしまうのです。
よって、editだけでなくupdateにも適用する必要があるのです。
同じ方法で削除ボタンを作ることもできますから、destroyにも適用してあげましょう。
結論
- ビューの条件分岐では不十分
- editだけを守っても不十分。updateやdestroyも守る必要がある。
- new、createの関係についても同様である。