astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

Play Framework 2.6でFilterに触れてみる

f:id:astamuse:20170815181256p:plain

こんにちは、開発部のyanagita@リモートワーク中です。
宮崎はだんだん暖かくなり、もうすこしで桜が咲き出しそうな雰囲気が漂ってます。
桜といえば春、春といえば出会いの季節です。
アスタミューゼでは多くの方との出会いを心待ちにしています。

前回は弊社のWeb Framework asta4dのscala対応について書きましたが、今回は元に戻ってPlay Frameworkに関する事でFilterについて書きたいと思います。

前提

今回もPlay Framework 2.6のScala版で説明します。Javaの方はJavaに読み替えて頂ければとm(_ _)m

Play Frameworkの標準Filterと設定

Play Framework 2.6では前バージョンの2.5から新しいFilterが一つ追加になり、5つのFilter機能が標準で使用可能になっています。

  1. Gzip encoding filter
  2. Security headers filter
  3. CORS filter
  4. CSRF filter
  5. Allowed hosts filter
  6. Redirect HTTPS filter ← 2.6から追加

このうち、Security header filter、CSRF filter、AllowedHostFilterはデフォルトで適用されるFilterになります。
もし、残りのFilterも適用したい場合はapplication.confにFilterの追加定義を行います。

# conf/application.conf
# Gzip filterを追加する例
play.filters.enabled += "play.filters.gzip.GzipFilter"

逆にFilterを外す場合

# conf/application.conf
#CORS filterを削除する例
play.filters.disabled += "play.filters.csrf.CSRFFilter"

次に各Filterのについて触れます。

Gzip encoding filter

Gzip encoding filterは、レスポンスデータのgzip圧縮をサポートするFilterです。
詳細な設定はapplication.confで行います。

# conf/application.conf
play.filters.gzip.contentType {

    # Gzip圧縮を行なうContent-Typeを設定(デフォルト値:空)
    whiteList = [ "text/*", "application/javascript", "application/json" ]

    # Gzip圧縮を行わないContent-Typeを設定(デフォルト値:空)
    blackList = []
}

whiteList、blackListが共に空の場合、全レスポンスがgzip圧縮の対象となります。
whiteListのみ設定した場合、設定したContent-Typeのレスポンスのみがgzip圧縮の対象となります。
blackListのみ設定した場合、設定したContent-Type以外のレスポンスがgzip圧縮の対象となります。 whiteList、blackList共に設定した場合、whiteListが優先されblackListは適用されないのでご注意下さい。

Security headers filter

セキュリティに関するHeaderパラメータを自動設定します。
各セキュリティパラメータの設定は下記の通りです。

# conf/application.conf
play.filters.headers {

    # X-Frame-Options設定。nullの場合は指定なし(デフォルト値:"DENY")
    frameOptions = "DENY"

    # X-XSS-Protection設定。nullの場合は指定なし(デフォルト値:"1; mode=block")
    xssProtection = "1; mode=block"

    # X-Content-Type-Options設定。nullの場合は指定なし(デフォルト値:"nosniff")
    contentTypeOptions = "nosniff"

    # X-Permitted-Cross-Domain-Policies設定。nullの場合は指定なし(デフォルト値:"master-only")
    permittedCrossDomainPolicies = "master-only"

    # Content-Security-Policy設定。nullの場合は指定なし(デフォルト値:"default-src 'self")
    contentSecurityPolicy = "default-src 'self'"

    # Referrer-Policy設定。nullの場合は指定なし(デフォルト値:"origin-when-cross-origin, strict-origin-when-cross-origin")
    referrerPolicy = "origin-when-cross-origin, strict-origin-when-cross-origin"
}

CORS filter

CORS(Cross-Origin Resource Sharing)は、ドメインの異なるWebアプリケーション間のリクエスト制御設定を行います。
こちらもapplication.confで設定を行います。

# conf/application.conf
play.filters.cors {

    # CORSを適用するルートパス(デフォルト値:/)
    pathPrefixes = ["/"]

    # アクセス許可するドメイン。nullの場合は制限無し(デフォルト値:null)
    # 指定する場合は、["astamuse.com", ...]
    allowedOrigins = null

    # preflightリクエストで許可するメソッド。nullの場合は制限なし(デフォルト値:null)
    # 指定する場合は、["GET", "POST"]
    allowedHttpMethods = null

    # preflightリクエストで許可するHttpヘッダ。nullの場合は制限なし(デフォルト値:null)
    # 指定する場合は、["Accept"]
    allowedHttpHeaders = null

    # 許可する独自のHttpヘッダ。nullの場合は制限なし(デフォルト値:null)
    exposedHeaders = []

    # Credentials情報の使用の有無(デフォルト値:true)
    supportsCredentials = true

    # CORSメタデータのキャッシュ有効期間(デフォルト値:1 hour)
    # 設定値はduration
    preflightMaxAge = 1 hour

    # pathPrefixesに該当しないパスへのアクセス許可有無(デフォルト値:false)
    serveForbiddenOrigins = false
  }

CSRF filter

CSRF (cross-site request forgeries) は、 2.6からデフォルトFilterに追加されたので2.5以前から移行される場合は対応が必要になります。
CSRFのチェックはForm内にtoken情報を含む必要があります。一般的なtoken情報の設定方法は下記の2パータンがあります。

  • action属性のパスにtoken情報を付加するケース

template.scala.html

@import helper._

@form(CSRF(routes.SampleController.index())) {
    ...
}

HTML

<form method="POST" action="/index?csrfToken=1234567890abcdef">
   ...
</form>

 
* formタグ内にパラメータを付加するケース

template.scala.html

@import helper._

@form(routes.SampleController.index()) {
   @CSRF.formField
    ...
}

HTML

<form method="POST" action="/index">
  <input type="hidden" name="csrfToken" value="1234567890abcdef"/>
   ...
</form>

Allowed hosts filter

有効host以外からのアクセスを遮断するFilterです。遮断時はHTTP codeは400を返します。
有効hostの設定もapplication.confで行います。

# conf/application.conf
play.filters.hosts {
    # 有効なホスト名を設定(デフォルト値:localhost, .local)
    allowed = ["localhost", ".local"]
  }

Allowed hosts filterはデフォルト設定のFilterになります。confファイルを環境別に用意している場合に、有効hostの設定が漏れていると環境を変えた時にアクセスできない問題が発生するので注意が必要です。
開発中などホスト制限を行わない場合は、"."を設定することでホスト制限なくアクセスできます。
サブドメインも含めてた制限を行なう場合は、"." + ホスト名で行えます。
(".astamuse.com"と設定した場合、"astamuse.com"、"sub.astamuse.com"が該当します。)
ポートが変更されている場合は、ポート番号を含んで設定します。
(localhostで8080ポートの場合、"localhost:8080")

Redirect HTTPS filter

httpでのアクセスをhttpsにリダイレクトするFilterです。リダイレクト時のHTTP codeはデフォルトで308になります。
308であればリダイレクト時のリクエストメソッドが変更されないので予期しないリクエストケースはなくなりますが古いブラウザでは動かない欠点があります。
別のcodeへの変更は下記の通り設定します。

# conf/application.conf(デフォルト値:308)
play.filters.https.redirectStatusCode = 301

さいごに

至れり尽くせりのFilterが揃ってます。
Play Frameworkに触れた際にはFilterにも是非触ってみて下さい。

アスタミューゼではまだまだエンジニア&デザイナを募集しています。
気になる方は下からご応募下さい!新しい出会いをメンバー一同お待ちしてます!

Copyright © astamuse company, ltd. all rights reserved.