PlayFramework でアクセスできるhostを制限する
概要
PlayFrameworkにはアクセスできるhostを制限できるFilterがあり、これはapplication.confファイル下記を設定することで、実現できる。
play.filters.hosts { allowed = [".example.com", "localhost:9000"] }
このフィルターはホワイトリスト形式で、example.com と、そのサブドメイン、それとlocalhost:9000からのリクエストを許可している。※サブドメインを含む許可は本番環境では非推奨
サブドメインの許可を表現しているのは .
(ドット)の部分で、これがワイルドカードのような役割を果たしてサブドメインを全て許可にしている。.
をつけず、example.com
のみにすれば、サブドメインは許可されない。
実際にやってみる
下記のfilterが設定されたPlayのアプリケーションを実行し、APIに問い合わせしてみる。
play.filters.hosts { allowed = ["localhost:9000"] }
これは、localhost:9000 のみを許可している。Playのアプリケーションはlocalhost:9000で待ち受けているので、このリクエストは当然通る。
これを下記のように少し書き換えて再度実行してみる。
play.filters.hosts { allowed = ["localhost:9999"] }
port番号を9000番から9999に変えてみた。すると、BadRequestとなり、リクエストが弾かれていることが分かる。
テスト
ドメインの許可設定が正常に稼働しているかを確認するテストを書いてみる。リクエストのテストになるので、とりあえずここではControlerのテストとして実装したサンプルを示す。
host として、example.com のみを許可しているという想定。
利用しているのは scalatestplus-play version 5.0.0。
package coc.interfaces.controllers import org.scalatestplus.play.PlaySpec import org.scalatestplus.play.guice.GuiceOneAppPerTest import play.api.http.HeaderNames import play.api.http.Status.{BAD_REQUEST, OK} import play.api.mvc.AnyContentAsEmpty import play.api.test.Helpers.{GET, defaultAwaitTimeout, route, status, writeableOf_AnyContentAsEmpty} import play.api.test.{FakeHeaders, FakeRequest} class CocControllerTest extends PlaySpec with GuiceOneAppPerTest { "CocControllerTest" should { "hostが example.com の時、Okを返す" in { val request = FakeRequest( method = GET, uri = "/coc/abilities", headers = FakeHeaders(Seq(HeaderNames.HOST -> "example.com")), body = AnyContentAsEmpty ) val result = route(app, request).get status(result) mustBe OK } "hostが example.jp の時 BadRequestを返す" in { val request = FakeRequest( method = GET, uri = "/coc/abilities", headers = FakeHeaders(Seq(HeaderNames.HOST -> "example.jp")), body = AnyContentAsEmpty ) val result = route(app, request).get status(result) mustBe BAD_REQUEST } } }
FakeRequest
の headers
のところを変えて、hostによる制御ができているかの確認をしている。