初学者でも、何かを送るものって意識はあるだろうけど、以下の意識は薄いのではないか。
フォームでは、何を・どこに・どのように・どんなinputで送るかが定義されている。
What, Where, How,( + Type of input)と覚えるとよいかも。(自己流です)
2W1HT・・・なんかいい語呂でもないかな。。。
まず、フォームの概要について押さえておく。
ここはRailsガイドに掲載されていないが、把握すべき基礎的な内容だ。
<form accept-charset="UTF-8" action="/users" method="post">
<input type="email" name="user[email]" value="[email protected]" />
<input type="text" name="user[name]" value="alice" />
<input type="text" name="user[age]" value="20" />
</form>
action: アクセス先のURL
method: HTTPメソッド
type: フォームの入力値の種類(text, email, radio, checkboxなど)
name: フォームの名前を示している
value: 値
アクションは、あくまでアクセス先のURLである。
間違いやすいので注意すること。
paramsハッシュの中身は、以下のとおりとなる。
{'user' => {'email' => '[email protected]'}, {'name' => 'alice'}, {'age' => 20} }
このような形で書くことで、params[:user]と書くことで、Userモデルに紐づく全てのハッシュを取得できる。また、以下のように取得するハッシュを制限することができる。
params.require(:user).permit(:email)
フォームでは、よくラベルタグを使う。
フォームを使うメリットは、2つある。
ラベルタグは、インプットタグと紐付ける。
紐付けにあたっては、labelのforとinputのidを同一にする。
以下の事例においては、cheeseで紐付けされている。
繰り返しになるが、nameはパラメータのkeyなので、勘違いしないように。
(keyというのは用語が適切でないかも。Hashのkey-valueのkey)
<div class="preference">
<label for="cheese">Do you like cheese?</label>
<input type="checkbox" name="cheese" id="cheese">
</div>
Form_withでは使われないが、labelタグにinputタグをネストすることでも紐付け可能。
<label>Do you like peas?
<input type="checkbox" name="peas">
</label>
Railsでフォームを作ると、文字エンコードとauthenticity_tokenが自動で含まれる。
authenticity_tokenはCSRF対策のため。GETメソッドの場合、このトークンは作成されない。
Railsサーバーに対して、このトークン抜きでリクエストを送っても拒否される。要注意。(ただし、Railsの設定次第ではトークン抜きでも受け付けることができたはず)
<%= form_tag do %>
Form contents
<% end %>
<form accept-charset="UTF-8" action="/home/index" method="post">
<div style="margin:0;padding:0">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
</div>
Form contents
</form>
CSRFとは、クロスサイトリクエストフォージェリーの略。
まず、リクエストフォージェリーに着目するとよさそう。
リクエストとは、サーバーに送るリクエストのこと。
例えば、ユーザー登録をするのは、クライアントからサーバーへのリクエスト。
フォージェリとは、偽物のこと。
で、リクエストフォージェリー。
これは、悪意のある人がJavaScriptなんかでこっそりコードを仕込んでおくことで、
その人の意志とは関係なく、サーバー側にリクエストを送ってしまうこと。
え、そんなことできるのかって。できる。
JavaScriptを使うと、例えば何かの要素をクリックした際に、
特定のURLに対してリクエストを送るよう指示を出すことができる。
この機能を使って、例えばtwitterにログインしているユーザーを対象にして、
クリックしたと同時に、そのユーザーに知らず知らずの内に、サーバー側にリクエストを投げることができる。
例えば、殺害予告ツイートの投稿リクエストを投げることができる。
ログインした状態で、まさにそのユーザーからリクエストが送られてしまうので、
このリクエストは受け入れられてしまい、意図していないのに殺害予告ツイートをしてしまうハメになる。
たぶん、概念的にはこんな感じの理解で大枠あっていると思う。
試してみると分かるが、このtokenはサーバー側から毎回ランダムに生成される。
同じページであっても、リロードすると変わるはずだ。
このトークンは、投稿時にサーバー側に併せて送られる。
そして、このトークンがサーバー側で事前に送ったものと一致するか検証がなされる。
つまり、イメージとしては、こんなかんじ。
まず、OKパターン。
NGパターン。
この開けゴマがtoken。
これがリロードする度に変わるので、サイトをまたいで、つまりクロスサイトで
フォージェリーなリクエストを送ることを防げる。
まず、これが自分の言葉で説明できるか考えてみよう。
<form accept-charset="UTF-8" action="/users" method="post">
<input type="email" name="user[email]" value="[email protected]" />
<input type="text" name="user[name]" value="alice" />
<input type="text" name="user[age]" value="20" />
</form>
次に、ラベルって何か自分の言葉説明できるか考えてみよう。
そして、空欄に何が入るか振り返ってみよう。
<div class="preference">
<label for="空欄">Do you like cheese?</label>
<input type="checkbox" name="cheese" id="cheese">
</div>
最後にauthenticity_tokenって何だったか自分の言葉で説明できるか考えてみよう。
自分で書いておきながら説明できないかも。。。
あと、これは書きダメベースなので、次回から尻すぼみます。