2
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Organization

Playframework+axiosによるPOSTするときの注意点(CSRFTokenとlist)

PlayFramework(twirl)によるform

PlayFrameworkにはtwirlというテンプレートエンジンが用意されている。

hoge.scala.html
@helper.form(action="/hoge/huga",Symbol("id")->"form1") {
@CSRF.formfield
@helper.inputText(nankanoForm("nanika"),Symbol("id")->"text1",Symbol("placeholder")->"field")
<input type="submit">
}

このようなテンプレートからレンダリングされたhtmlでsubmitすれば入力したデータが
GET/POSTされ用意したnankanoformのcase classなどで受け取ることが出来るが、
クライアント側でajaxリクエストを行うといくつか問題が発生する。

CSRF対策(POST時)

PlayframeworkではCSRFfilterを有効にするとRequestにCSRFTokenが設定されてないものは不正リクエストとして弾く。

上記テンプレートのように@CSRF.formfield
@helper.formのブロック内部に追加することでCSRFfilterの認証を通すことができる。
しかし単純にformの値を取ってきてPOSTをすると、
CSRFTokenが見つからないためにリクエストエラーになってしまう。

PlayFrameworkではFormDataとしてcsrfTokenを含めるという方法を取っている。
上記のテンプレートをレンダリングした結果としてhoge.htmlがクライアント側で表示される。

hoge.html
<form action="hoge/huga" method=POST id="form1">
<input name="csrfToken" value="123...">
<input type="text" name="nanika" id="text1" placeholder="field">
<input type="submit">
</form>

このform内のcsrfTokenの値を取得してPOSTする。


const params = new URLSearchParams()

const csrfToken= document.getElementsByName("csrfToken")[0].value
const text = document.getElementById("text1").value

params.append("csrfToken",csrfToken)
params.append("text1",text)

axios.post("/hoge/huga",params)

一応こういう感じにcsrfTokenに対応させる形で送ると普通にsubmitしたのと同じようにリクエストが通る(もっといい書き方がある気もする)。

上記の方法を取らなくてもapplication.confにsession.sameSite = "lax"と設定してCSRFfilterをfalseにしたり、
routesを以下のようにしてもいいと思う。

+nocsrf
POST /hoge/huga 

他にもplay.filters.csrf.header.bypassHeadersに色々設定して認証を回避したりもできる。
https://www.playframework.com/documentation/2.8.x/ScalaCsrf

listのPOST

formの定義時にlist(number)という風にするとList[Int]みたいな感じで受け取れる。
例えばboxes -> list(number)みたいな感じにするとhtmlではname=boxes[]でinput要素が生成される。
これをPOSTする際には下記のようにする必要がある。


Array.from(document.getElementsByName("boxes[]"))
     .filter(e => e.checked)
     .map(e => e.value)
     .forEach(v => params.append("boxes[]",v))

配列としてappendするのではなく、各要素の値をappendしなければformのcase classへの変換が上手くいかないので注意。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
2
Help us understand the problem. What are the problem?