ドキュメント

§組み込みHTTPフィルター

Playは、アプリケーションのHTTP動作を変更できるいくつかの標準フィルターを提供しています。 独自のフィルターは、JavaまたはScalaのいずれかで記述することもできます。

§デフォルトフィルター

Playには、設定を介して定義された、有効化されたデフォルトのフィルターセットが付属するようになりました。プロパティplay.http.filtersがnullの場合、デフォルトはplay.api.http.EnabledFiltersになり、play.filters.enabled設定プロパティに完全修飾クラス名で定義されたフィルターがロードされます。

Play自体では、play.filters.enabledは空のリストです。しかし、フィルターライブラリはPlayFiltersというAutoPluginとしてsbtに自動的にロードされ、play.filters.enabledプロパティに以下の値を追加します。

つまり、新しいプロジェクトでは、CSRF保護(ScalaCsrf / JavaCsrf)、SecurityHeaders、およびAllowedHostsFilterがすべて自動的に定義されます。

デフォルトリストに追加するには、+=を使用します。

play.filters.enabled+=MyFilter

以前にplay.api.http.DefaultHttpFiltersを拡張して独自のフィルターを定義していた場合は、コード内でEnabledFiltersと独自のフィルターを組み合わせることもできます。

Java
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import play.api.http.EnabledFilters;
import play.filters.cors.CORSFilter;
import play.http.DefaultHttpFilters;
import play.mvc.EssentialFilter;

public class Filters extends DefaultHttpFilters {

  @Inject
  public Filters(EnabledFilters enabledFilters, CORSFilter corsFilter) {
    super(combine(enabledFilters.asJava().getFilters(), corsFilter.asJava()));
  }

  private static List<EssentialFilter> combine(
      List<EssentialFilter> filters, EssentialFilter toAppend) {
    List<EssentialFilter> combinedFilters = new ArrayList<>(filters);
    combinedFilters.add(toAppend);
    return combinedFilters;
  }
}
Scala
import javax.inject.Inject

import play.api.http.DefaultHttpFilters
import play.api.http.EnabledFilters
import play.filters.cors.CORSFilter

class Filters @Inject() (enabledFilters: EnabledFilters, corsFilter: CORSFilter)
    extends DefaultHttpFilters(enabledFilters.filters :+ corsFilter: _*)

それ以外の場合、ルートにFiltersクラスがあるか、play.http.filtersが明示的に定義されている場合、後述のEnabledFilters機能よりも優先されます。

§デフォルトフィルターのテスト

複数のフィルターが有効になっているため、すべてのテストがパスし、リクエストが有効であることを確認するために、機能テストをわずかに変更する必要がある場合があります。たとえば、HostHTTPヘッダーがlocalhostに設定されていないリクエストは、AllowedHostsFilterを通過せず、代わりに400 Forbidden応答を返します。

§AllowedHostsFilterを使用したテスト

AllowedHostsFilterフィルターが自動的に追加されるため、機能テストではHost HTTPヘッダーを追加する必要があります。

FakeRequestまたはHelpers.fakeRequestを使用している場合、HostHTTPヘッダーは自動的に追加されます。play.mvc.Http.RequestBuilderを使用している場合は、ヘッダーを手動で追加する独自の行を追加する必要がある場合があります。

Http.RequestBuilder request =
    new Http.RequestBuilder()
        .method(GET)
        .header(Http.HeaderNames.HOST, "localhost")
        .uri("/xx/Kiwi");

§CSRFFilterを使用したテスト

CSRFFilterフィルターが自動的に追加されるため、CSRF.formFieldを含むTwirlテンプレートをレンダリングするテスト、つまり

@(userForm: Form[UserData])(implicit request: RequestHeader, m: Messages)

<h1>user form</h1>

@request.flash.get("success").getOrElse("")

@helper.form(action = routes.UserController.userPost()) {
  @helper.CSRF.formField
  @helper.inputText(userForm("name"))
  @helper.inputText(userForm("age"))
  <input type="submit" value="submit"/>
}

には、リクエストにCSRFトークンを含める必要があります。Scala APIでは、play.api.test.CSRFTokenHelper._をインポートすることでこれを実行します。これにより、play.api.test.FakeRequestwithCSRFTokenメソッドで強化されます。

import org.specs2.mutable.Specification
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.test.CSRFTokenHelper._
import play.api.test.FakeRequest
import play.api.test.Helpers._
import play.api.test.WithApplication

class UserControllerSpec extends Specification {
  "UserController GET" should {
    "render the index page from the application" in new WithApplication() {
      override def running() = {
        val controller = app.injector.instanceOf[UserController]
        val request    = FakeRequest().withCSRFToken
        val result     = controller.userGet().apply(request)

        status(result) must beEqualTo(OK)
        contentType(result) must beSome("text/html")
      }
    }
  }
}

Java APIでは、play.mvc.Http.RequestBuilderインスタンスでCSRFTokenHelper.addCSRFTokenを呼び出すことでこれを実行します。

Http.RequestBuilder request = new Http.RequestBuilder().method(POST).uri("/xx/Kiwi");

request = CSRFTokenHelper.addCSRFToken(request);

§デフォルトフィルターの無効化

フィルターを無効にする最も簡単な方法は、application.confplay.filters.disabledリストに追加することです。

play.filters.disabled+=play.filters.hosts.AllowedHostsFilter

これは、デフォルトフィルターを通過させたくない機能テストがある場合に役立つ場合があります。

デフォルトフィルターを削除するには、リスト全体を手動で設定できます。

play.filters.enabled=[]

すべてのフィルタークラスを削除する場合は、disablePluginsメカニズムを使用して無効にすることができます。

lazy val root = project.in(file(".")).enablePlugins(PlayScala).disablePlugins(PlayFilters)

GuiceApplicationBuilderを含む機能テストを作成している場合は、configureを呼び出すことでテストですべてのフィルターを無効にすることができます。

class UserControllerWithoutFiltersSpec extends Specification {
  "UserControllerWithoutFiltersSpec GET" should {
    "render the index page from the application" in new WithApplication(
      GuiceApplicationBuilder().configure("play.http.filters" -> "play.api.http.NoHttpFilters").build()
    ) {
      override def running() = {
        val controller = app.injector.instanceOf[UserController]
        val request    = FakeRequest().withCSRFToken
        val result     = controller.userGet().apply(request)

        status(result) must beEqualTo(OK)
        contentType(result) must beSome("text/html")
      }
    }
  }
}

§コンパイル時デフォルトフィルター

コンパイル時依存性注入を使用している場合、デフォルトフィルターは実行時ではなく、コンパイル時に解決されます。

つまり、play.api.BuiltInComponentsトレイト(Scala用)とplay.BuiltInComponentsインターフェース(Java用)には、抽象のまま残されているhttpFiltersメソッドが含まれるようになりました。フィルターのデフォルトリストは、Scalaのplay.filters.HttpFiltersComponentsとJavaのplay.filters.components.HttpFiltersComponentsで定義されています。そのため、ほとんどの場合、HttpFiltersComponentsをミックスインして独自のフィルターを追加することをお勧めします。

Java
import play.ApplicationLoader;
import play.BuiltInComponentsFromContext;
import play.filters.components.HttpFiltersComponents;
import play.mvc.EssentialFilter;
import play.routing.Router;

import java.util.ArrayList;
import java.util.List;

public class MyAppComponents extends BuiltInComponentsFromContext implements HttpFiltersComponents {

  public MyAppComponents(ApplicationLoader.Context context) {
    super(context);
  }

  @Override
  public List<EssentialFilter> httpFilters() {
    List<EssentialFilter> combinedFilters =
        new ArrayList<>(HttpFiltersComponents.super.httpFilters());
    combinedFilters.add(new LoggingFilter(materializer()));
    return combinedFilters;
  }

  @Override
  public Router router() {
    return Router.empty(); // implement the router as needed
  }
}
Scala
import org.apache.pekko.util.ByteString
import play.api.libs.streams.Accumulator
import play.api.mvc.EssentialAction
import play.api.mvc.EssentialFilter
import play.api.mvc.RequestHeader
import play.api.mvc.Result
import play.api.routing.Router
import play.api.ApplicationLoader
import play.api.BuiltInComponentsFromContext
import play.api.NoHttpFiltersComponents
import play.filters.csrf.CSRFFilter

class MyAppComponents(context: ApplicationLoader.Context)
    extends BuiltInComponentsFromContext(context)
    with play.filters.HttpFiltersComponents {
  lazy val loggingFilter = new LoggingFilter()

  override def httpFilters: Seq[EssentialFilter] = {
    super.httpFilters :+ loggingFilter
  }

  override def router: Router = Router.empty // implement the router as needed
}

リストから要素をフィルターアウトする場合は、次の手順を実行します。

Java
public class MyAppComponents extends BuiltInComponentsFromContext implements HttpFiltersComponents {

  public MyAppComponents(ApplicationLoader.Context context) {
    super(context);
  }

  @Override
  public List<EssentialFilter> httpFilters() {
    return HttpFiltersComponents.super.httpFilters().stream()
        .filter(filter -> !filter.getClass().equals(CSRFFilter.class))
        .collect(Collectors.toList());
  }

  @Override
  public Router router() {
    return Router.empty(); // implement the router as needed
  }
}
Scala
class MyAppComponents(context: ApplicationLoader.Context)
    extends BuiltInComponentsFromContext(context)
    with play.filters.HttpFiltersComponents {
  override def httpFilters: Seq[EssentialFilter] = {
    super.httpFilters.filterNot(_.getClass == classOf[CSRFFilter])
  }

  override def router: Router = Router.empty // implement the router as needed
}

§コンパイル時デフォルトフィルターの無効化

デフォルトフィルターを無効にするには、Scalaのplay.api.NoHttpFiltersComponentsとJavaのplay.filters.components.NoHttpFiltersComponentsをミックスインします。

Java
public class MyAppComponents extends BuiltInComponentsFromContext
    implements NoHttpFiltersComponents {

  public MyAppComponents(ApplicationLoader.Context context) {
    super(context);
  }

  // no need to override httpFilters method

  @Override
  public Router router() {
    return Router.empty(); // implement the router as needed
  }
}
Scala
class MyAppComponents(context: ApplicationLoader.Context)
    extends BuiltInComponentsFromContext(context)
    with NoHttpFiltersComponents {
  override def router: Router = Router.empty // implement the router as needed
}

Scalaのplay.api.NoHttpFiltersComponentsplay.filters.components.NoHttpFiltersComponentsの両方には、フィルターの空のリストを返すhttpFiltersメソッドがあります。

次へ: gzipエンコードの設定


このドキュメントにエラーを見つけましたか?このページのソースコードはこちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを自由に投稿してください。ご質問やアドバイスがありましたら、コミュニティフォーラムにアクセスして、コミュニティとの会話を開始してください。