Play 2.6の移行ガイド【翻訳】

https://www.playframework.com/documentation/2.6.x/Migration26 を google翻訳した

-----

# Play 2.6移行ガイド

これは、Play 2.5からPlay 2.6に移行するためのガイドです。以前のバージョンのPlayから移行する必要がある場合は、まず [Play 2.5移行ガイド](https://www.playframework.com/documentation/2.6.x/Migration25) に従ってください。

## 移行する方法

sbtでPlayプロジェクトをロード/実行するには、次の手順を実行してsbtビルドを更新する必要があります。

### Playアップグレード

play / playins.sbtのPlayバージョン番号を更新してPlayをアップグレードします。

```scala
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.x")
```

2.6.xの "x"は、使用したいPlayのマイナーバージョンです(例：2.6.0)。

### 0.13.15にsbtをアップグレード

Play 2.6では、最新のsbtバージョン0.13.15にアップグレードする必要があります。 0.13.15のsbtリリースには [いくつかの改善とバグ修正](http://www.scala-sbt.org/0.13/docs/sbt-0.13-Tech-Previews.html#sbt+0.13.15) があります( [sbt 0.13.13](http://www.scala-sbt.org/0.13/docs/sbt-0.13-Tech-Previews.html#sbt+0.13.13) の変更も参照)。

更新するには、 `project/build.properties` を次のように変更します。

```
sbt.version=0.13.15
```

### Guice DIのサポートが別のモジュールに移動

Play 2.6では、コアPlayモジュールにGuiceが含まれなくなりました。 libraryDependenciesにguiceを追加してGuiceモジュールを設定する必要があります：

```scala
libraryDependencies += guice
```

### OpenIDのサポートを別のモジュールに移動

Play 2.6では、コアPlayモジュールは、play.api.libs.openid(Scala)およびplay.libs.openid(Java)にOpenIDサポートを含まなくなりました。これらのパッケージを使用するには libraryDependenciesにopenIdを追加してください：

```scala
libraryDependencies += openId
```

### Play JSON を別プロジェクトに移動

Play JSONが https://github.com/playframework/play-json でホストされ別のライブラリに移動しました。 Play JSONはPlayの残りの部分に依存しないので、PlayImportのjson値はSBTビルドではもう機能しません。代わりに、ライブラリを手動で指定する必要があります。

```scala
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.0"
```

また、play-jsonにはコアPlayライブラリとは別のリリースサイクルがあり、バージョンはPlayのバージョンと同期していません。

### Play Iteratees を別のプロジェクトに移動

Play Iterateesは、 https://github.com/playframework/play-iteratees でホストされている別のライブラリに移動されました。 Play Iteratees は Playの残りの部分に依存しないため、主な変更点は、ライブラリを手動で指定する必要があることです。

```scala
libraryDependencies += "com.typesafe.play" %% "play-iteratees" % "2.6.1"
```

このプロジェクトには、Iterateesと [Reactive Streams](http://www.reactive-streams.org/) を統合するサブプロジェクトもあります。次の依存関係も追加する必要があります。

```scala
libraryDependencies += "com.typesafe.play" %% "play-iteratees-reactive-streams" % "2.6.1"
```

> 注： ヘルパークラス `play.api.libs.streams.Streams` は `play-iteratees-reactive-streams` に移動され、現在は `play.api.libs.iteratee.streams.IterateStreams` と呼ばれています。したがって、Iteratees依存関係を追加し、必要に応じて新しいクラスを使用する必要があります。

最後に、Play Iterateesは別のバージョン管理方式を採用しているため、バージョンはPlayバージョンと同期しなくなりました。

## デフォルトのサーバーエンジンとしてのAkka HTTP

Playはデフォルトのバックエンドとして [Akka-HTTP](http://doc.akka.io/docs/akka-http/current/scala.html) サーバーエンジンを使用します。何らかの理由(たとえば、Nettyの [ネイティブトランスポート](http://netty.io/wiki/native-transports.html) を使用している場合など)でNettyに戻す必要がある場合は、 [Netty Server](https://www.playframework.com/documentation/2.6.x/NettyServer) のマニュアルでその方法を参照してください。

[Akka HTTP Server Backend](https://www.playframework.com/documentation/2.6.x/AkkaHttpServer) で詳しく読むことができます。

### Akka HTTPサーバーのタイムアウト

Play 2.5.xには、デフォルトのサーバーバックエンドである [Netty Server](https://www.playframework.com/documentation/2.6.x/NettyServer )のリクエストタイムアウト設定はありません。しかし、Akka HTTPは、アイドル状態の接続とリクエストの両方にタイムアウトがあります(詳細については、 [Akka HTTP Settings](https://www.playframework.com/documentation/2.6.x/SettingsAkkaHttp) のドキュメントを参照してください)。 [Akka HTTPドキュメント](http://doc.akka.io/docs/akka-http/10.0.7/scala/http/common/timeouts.html#akka-http-timeouts) には、

> Akka HTTPには、悪意のある攻撃やプログラミングミスからサーバーを保護するためのさまざまな組み込みのタイムアウトメカニズムが付属しています。

[ここ](http://doc.akka.io/docs/akka-http/current/scala/http/configuration.html) で、 `akka.http.server.idle-timeout` 、 `akka.http.server.request-timeout` 、および `akka.http.server.bind-timeout` のデフォルト値を確認できます。 Playには [タイムアウトを定義するための独自の設定](https://www.playframework.com/documentation/2.6.x/SettingsAkkaHttp) があります。したがって、503 Service Unavailableの数が表示されるようになったら、設定をアプリケーションにとってより合理的な値に変更することができます。

```
play.server.http.idleTimeout = 60s
play.server.akka.requestTimeout = 40s
```

## Scalaモードの変更

Scala [Mode](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/Mode.html) は Enumeration から case オブジェクトにリファクタリングされました。このリファクタリングにより、ほとんどのScalaコードは変更されません。しかし、あなたのJavaコードでScala Modeの値にアクセスしている場合、それを以下から変更する必要があります：

```java
//このJavaコードを検討する
play.api.Mode scalaMode = play.api.Mode.Test();
```

次のものに書き直さなければなりません：

```java
//このJavaコードを検討する
play.api.Mode scalaMode = play.Mode.TEST.asScala();
```

JavaとScalaモード間の変換も簡単です。

```java
// Javaコード内
play.api.Mode scalaMode = play.Mode.DEV.asScala();
```

またはあなたのScalaコードで：

```scala
play.Mode javaMode = play.api.Mode.Dev.asJava
```

また、 `play.api.Mode.Mode` は現在廃止予定です。代わりに `play.api.Mode` を使用してください。

## `Writeable[JsValue]` の変更

以前は、デフォルトのScala `Writeable[JsValue]` では暗黙的なコーデックを定義することができました。異なるコーデックを使用して記述することができます。これは、 `application/json` がテキストベースのコンテンツタイプのように動作しないため、問題になる可能性があります。 Unicode文字セット(UTF-8、UTF-16およびUTF-32)のみが可能で、多くのテキストベースのコンテンツタイプのように `charset` パラメータは定義されていません。

現在、デフォルトの `Writeable[JsValue]` には暗黙のパラメータはなく、常に UTF-8 に書き込みます。ほとんどのユーザーはJSONのためにUTF-8を使用したいので、大部分のケースをカバーしています。また、JSONをバイト配列に書き込むためのより効率的な組み込みメソッドを簡単に使用することもできます。

古い動作が必要な場合は、希望のコーデックと Content-Typeの `play.api.http.Writeable.writeableOf_JsValue(codec, contentType)`を使用して任意のコーデックで書き込み可能を定義できます。

## Scala コントローラの変更

慣用的なPlayコントローラは、これまで、必要なグローバル状態を有していた。必要な主要な場所は、グローバル [Action](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/Action$.html) オブジェクトと [`BodyParsers＃parse`](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/BodyParsers.html#parse:play.api.mvc.PlayBodyParsers) メソッドでした。

その状態を注入する新しい方法をいくつかの新しいコントローラクラスに提供し、同じ構文を提供しました：

  * [BaseController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/BaseController.html) ：インプリメンテーションクラスによって提供される抽象 [ControllerComponents](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/ControllerComponents.html) を持つトレイト。
  * [AbstractController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/AbstractController.html) ：コンストラクタインジェクションを使用して注入できる [ControllerComponents](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/ControllerComponents.html) コンストラクタパラメータで [BaseController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/BaseController.html) を拡張する抽象クラス。
  * [InjectedController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/InjectedController.html) ：メソッド挿入( `setControllerComponents` メソッドを呼び出す)によって [ControllerComponents](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/ControllerComponents.html) を取得する、 [BaseController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/BaseController.html) を拡張する特性。 GuiceのようなランタイムDIフレームワークを使用している場合、これは自動的に行われます。

[ControllerComponents](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/ControllerComponents.html) は、コントローラで一般的に使用されるコンポーネントをバンドルするためのものです。 [ControllerHelpers](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/ControllerHelpers.html) を拡張し、独自のコンポーネントバンドルを注入することで、独自のベースコントローラを作成することもできます。 Playでは、コントローラが特定の特性を実装する必要はありません。

[BaseController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/BaseController.html) は、 [Action](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/Action.html) と `parse` が、グローバルオブジェクトではなく、注入されたインスタンスを参照するようにします。これは、通常は実行したいものです。

[AbstractController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/AbstractController.html) を使用したコードの例を次に示します。

```scala
class FooController @Inject() (components: ControllerComponents)
    extends AbstractController(components) {

  // Action and parse now use the injected components
  def foo = Action(parse.json) {
    Ok
  }
}
```

BaseController の場合：

```scala
class FooController @Inject() (val controllerComponents: ControllerComponents) extends BaseController {

  // Action and parse now use the injected components
  def foo = Action(parse.json) {
    Ok
  }
}
```

InjectedController の場合：

```scala
class FooController @Inject() (val controllerComponents: ControllerComponents) extends BaseController {

  // Action and parse now use the injected components
  def foo = Action(parse.json) {
    Ok
  }
}
```

`InjectedController` は、JSR-330準拠の依存関係注入によって自動的に呼び出される `setControllerComponents` メソッドを呼び出すことによって `ControllerComponents` を取得します。コンパイル時DIで `InjectedController` を使用することはお勧めしません。コントローラを手作業で広範囲にユニットテストする予定がある場合は、 `InjectedController` が依存関係を隠すので避けることをおすすめします。

個別の依存関係を手動で渡すことを希望する場合は、代わりにそれを行い、依存関係や状態のない [ControllerHelpers](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/ControllerHelpers.html) を拡張することができます。ここに例があります：

```scala
class Controller @Inject() (
    action: DefaultActionBuilder,
    parse: PlayBodyParsers,
    messagesApi: MessagesApi
  ) extends ControllerHelpers {
  def index = action(parse.text) { request =>
    Ok(messagesApi.preferred(request)("hello.world"))
  }
}
```

## Scala ActionBuilderとBodyParserの変更点

Scala [ActionBuilder](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/ActionBuilder.html) のトレイトは、ボディの型を型パラメータとして指定し、抽象パーサメンバをデフォルトボディパーサとして追加するように変更されました。あなたはあなたの ActionBuilder を修正し、ボディパーサを直接渡す必要があります。

[Action](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/Action$.html) グローバルオブジェクトと [`BodyParsers＃parse`](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/BodyParsers.html#parse:play.api.mvc.PlayBodyParsers) は現在廃止予定です。それらはそれぞれ注入可能なトレイト、 [DefaultActionBuilder](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/DefaultActionBuilder.html) および [PlayBodyParsers](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/PlayBodyParsers.html) に置き換えられます。コントローラの中にいる場合は、新しい [BaseController](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/BaseController.html) トレイトによって自動的に提供されます(上記の [Scala コントローラの変更] を参照してください)。

## クッキー

Javaユーザーの場合、 [play.mvc.Http.Cookie.builder](https://www.playframework.com/documentation/2.6.x/api/java/play/mvc/Http.Cookie.html#builder-java.lang.String-java.lang.String-) を使用して新しい Cookie を作成することをお勧めします。

```java
Http.Cookie cookie = Cookie.builder("color", "blue")
  .withMaxAge(3600)
  .withSecure(true)
  .withHttpOnly(true)
  .withSameSite(SameSite.STRICT)
  .build();
```

これは普通のコンストラクタ呼び出しよりも読みやすく、今後クッキー属性を追加/削除するとソースと互換性があります。

### SameSite属性(セッションとフラッシュ用に有効)

現在、Cookieには [SameSite属性](http://httpwg.org/http-extensions/draft-ietf-httpbis-cookie-same-site.html) が追加されており、CSRFを防止するために使用できます。次の3つの状態が考えられます。

  * `SameSite` がない。つまり、そのドメインへのすべてのリクエストに対してCookieが送信されます。
  * `SameSite=Strict` クロスサイトリクエストではなく、同じサイトリクエスト(サイトの別のページからのもの)に対してのみクッキーが送信されることを意味します。
  * `SameSite=Lax` つまり、トップレベルのナビゲーションとしてクロスサイトリクエストに対してクッキーが送信されますが、それ以外の場合は同じサイトリクエストに対してのみ送信されます。これにより、ほとんどのサイトで正しいことが実行されますが、ポップアップウィンドウを起動して実行される攻撃などの特定の種類の攻撃は防げません。

さらに、デフォルトで `SameSite=Lax` を使用するようにセッションCookieとFlash Cookieを移動しました。設定を使ってこれを微調整することができます。例えば：

```
play.http.session.sameSite = null // no same-site for session
play.http.flash.sameSite = "strict" // strict same-site for flash
```

> 注：この機能は現在、 [多くのブラウザでサポートされていない](http://caniuse.com/#feat=same-site-cookie-attribute) ため、使用しないでください。 ChromeとOperaは現在SameSiteをサポートする唯一の主要なブラウザです。

### `__Host` と `__Secure` プレフィックス

また、 [`__Host` と `__Secure` のCookie名のプレフィックス](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-prefixes-00#section-3) もサポートしました。

これは、Cookie名にこれらのプレフィックスを使用している場合にのみ影響します。もしあなたがそうであれば、適切な属性が設定されていない場合、それらのクッキーをシリアライズおよびデシリアライズするときにPlayが警告し、自動的にそれらを設定します。警告を削除するには、Cookieにこれらの接頭辞を使用しないか、次のように属性を設定する必要があります。

  * `__Host-` で指定されたCookieは、 `Path=/` および `Secure` 属性を設定する必要があります。
  * `__Secure-` で名前が付けられたCookieは、 `Secure` 属性を設定する必要があります。


## Assets

### コンパイル時DIを使用したアセットのバインド

コンパイル時DIを使用している場合は、 [controllers.AssetsComponents](https://www.playframework.com/documentation/2.6.x/api/scala/controllers/AssetsComponents.html) をミックスインして、コントローラインスタンスで `assets:Asset` を取得する必要があります。

```scala
class MyComponents(context: Context) extends BuiltInComponentsFromContext(context) with AssetsComponents {
  lazy val router = new Routes(httpErrorHandler, assets)
}
```

`lazy val assets: Assets` を持つ場合は、削除することができます。

### Assets の構成

既存のユーザー向けAPIは変更されていませんが、[AssetsFinder](https://www.playframework.com/documentation/2.6.x/api/scala/controllers/AssetsFinder.html) APIに移り、アセットを探し、設定でアセットディレクトリを設定することをお勧めします。

```
play.assets {
  path = "/public"
  urlPrefix = "/assets"
}
```

ルートでは次のことができます：

```
# prefix must match `play.assets.urlPrefix`
GET /assets/*file           controllers.Assets.at(file)
GET /versionedAssets/*file  controllers.Assets.versioned(file)
```

引数リストの先頭にアセットのパスを指定する必要はなくなりました。これは設定から​​読み込まれるためです。

テンプレートでは、 [`AssetsFinder＃path`](https://www.playframework.com/documentation/2.6.x/api/scala/controllers/AssetsFinder.html#path(rawPath:String):String) を使ってアセットの最終パスを見つけることができます：

```
@(assets: AssetsFinder)

<img alt="hamburger" src="@assets.path("images/hamburger.jpg")">
```


`Assets.versioned` を使用して引き続き逆ルートを使用することはできますが、複数のアプリケーションを一度に実行する場合は、問題の原因になる可能性がある最終的なアセット名に指定したアセット名を変換する必要があります。

## フォームの変更

Play 2.6以降、POST、PUT、またはPATCHリクエストと組み合わせて [bindFromRequest()](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/data/Form.html#bindFromRequest()(implicitrequest:play.api.mvc.Request[_]):play.api.data.Form[T]) を使用すると、クエリ文字列パラメータはフォームインスタンスにバインドされなくなります。

このリリースでは、2.5で既に廃止されていた静的メソッド( `DynamicForm.form()` など)は削除されました。移行方法について詳しくは、 [Play 2.5移行ガイド](https://www.playframework.com/documentation/2.6.x/Migration25) を参照してください。

### Javaフォームの変更

[play.data.Form](https://www.playframework.com/documentation/2.6.x/api/java/play/data/Form.html) インスタンスの [errors()](https://www.playframework.com/documentation/2.6.x/api/java/play/data/Form.html#errors--) メソッドは廃止予定です。 Map<String, List<ValidationError>> の代わりに単純な List<ValidationError> を返す `allErrors()` を代わりに使用する必要があります。 Play 2.6以前では `.errors().get("key")` を呼び出したところで、単に `.errors("key")` を呼び出すことができます。

これ以降、フォームクラス内で実装された `validate` メソッド(通常はクロスフィールド検証に使用される)は、クラスレベルの制約の一部です。このような制約の使用方法の詳細については、 [高度な検証ドキュメント](https://www.playframework.com/documentation/2.6.x/JavaForms#advanced-validation) を参照してください。
影響を受けるフォームクラスに `@Validate` で注釈を付け、 `validate` メソッドの戻り値の型に応じて、適切なtype引数(すべてが [play.data.validation.Constraints](https://www.playframework.com/documentation/2.6.x/api/java/play/data/validation/Constraints.html) で定義されています)で [Validatable](https://www.playframework.com/documentation/2.6.x/api/java/play/data/validation/Constraints.Validatable.html) インターフェイスを実装することで、既存の `validate` メソッドを簡単に移行できます:

|戻り値の型|実装するインタフェース|
|--------+----------------|
|String   |  Validatable<String>|
|ValidationError  |  Validatable<ValidationError>|
|List<ValidationError>  |  Validatable<List<ValidationError>>|
|Map<String,List<ValidationError>> (not supported anymore; use List instead)  |  Validatable<List<ValidationError>>|

(これ以上サポートされていない; Listを代わりに使用する)Validatable <List <ValidationError >>
たとえば、次のような既存のフォーム：

```java
public class MyForm {
    //...
    public String validate() {
        //...
    }
}
```

変更する必要があります：

```java
import play.data.validation.Constraints.Validate;
import play.data.validation.Constraints.Validatable;

@Validate
public class MyForm implements Validatable<String> {
    //...
    @Override
    public String validate() {
        //...
    }
}
```

> 注意：以前のすべての制約が以前に成功した後にのみ、「古い」検証メソッドが呼び出されました。しかし、デフォルトでは、クラスレベルの制約は、他の制約アノテーションと同時に呼び出されます(パスの合否に関係なく)。制約間に順序を定義するために、制約グループを使用できるようになりました。

## JPA移行ノート

[JPA移行ノート](https://www.playframework.com/documentation/2.6.x/JPAMigration26) を参照してください。

## I18n移行ノート

[「I18N APIの移行」](https://www.playframework.com/documentation/2.6.x/MessagesMigration26) を参照してください。

## キャッシュAPI移行ノート

[「キャッシュAPIの移行」](https://www.playframework.com/documentation/2.6.x/CacheMigration26) を参照してください。

## Java Configuration API移行ノート

[Java Configuration Migration](https://www.playframework.com/documentation/2.6.x/JavaConfigMigration26) を参照してください。

## Scala 設定API

Scalaの [play.api.Configuration](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/Configuration.html) APIには、 [ConfigLoader](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/ConfigLoader.html) を使用してあらゆるタイプの読み込みを可能にする新しいメソッドが追加されました。これらの新しい方法では、構成ファイルに構成キーが存在することが期待されます。たとえば、次の古いコードです。

```scala
val myConfig: String = configuration.getString("my.config.key").getOrElse("default")
```

変更する必要があります

```scala
val myConfig: String = configuration.get[String]("my.config.key")
```

`my.config.key = default` という設定で値 "default" を設定する必要があります。

また、デフォルト値を取得するためにコードでカスタムロジックが必要な場合は、設定ファイル( `my.config.key = null` )でデフォルトをnullに設定し、 `Option[T]` を読むことができます。

```scala
val myConfigOption: Option[String] = configuration.get[Option[String]]("my.config.key")
val myConfig: String = myConfigOption.getOrElse(computeDefaultValue())
```

また、 `getBooleanList` のようなJava型を返す古い [play.api.Configuration](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/Configuration.html) にはいくつかのメソッドがあります。可能であれば、Scalaバージョンの `get[Seq[Boolean]]` を使用することをお勧めします。それが不可能な場合は、基礎となる `underling`Config オブジェクトにアクセスし、そこから `getBooleanList` を呼び出すことができます。

既存のメソッドの非推奨メッセージには、各メソッドの移行方法も説明されています。 [play.api.Configuration](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/Configuration.html) の適切な使い方の詳細については、[Scala Configurationドキュメント](https://www.playframework.com/documentation/2.6.x/ScalaConfig) を参照してください。

## Play JSON APIの変更

### JSON配列インデックスの参照

Scala play-json APIを使用している場合は、JsLookup暗黙クラスの動作に少し変更があります。たとえば、次のようなコードがあるとします。

```scala
val bar = (jsarray(index) \ "bar").as[Bar]
```

indexは配列インデックスで、jsarrayはJsArrayです。これで、次のように記述する必要があります。

```scala
val bar = (jsarray \ index \ "bar").as[Bar]
```

これは、Scalaの他のコレクションのインデックスに沿った `JsArrays` のインデックス作成の動作を実現するために行われました。これで、 `jsarray(index)` メソッドはインデックスの値を返し、存在しなければ例外をスローします。

## 削除されたAPI

### 削除されたCrypto API

Crypto APIは、廃止予定のクラス `play.api.libs.Crypto、play.libs.Crypto` および `AESCTRCrypter` を削除しました。 `Crypto` へのCSRF参照は `CSRFTokenSigner` に置き換えられました。 `Crypto` へのセッションCookieの参照が `CookieSigner` に置き換えられました。詳細については、 [CryptoMigration25](https://www.playframework.com/documentation/2.6.x/CryptoMigration25) を参照してください。

### Akka廃止されたメソッドが削除されました

廃止予定の静的メソッド `play.libs.Akka.system` および `play.api.libs.concurrent.Akka.system` が削除されました。依存関係注入を使用して `ActorSystem` のインスタンスを取得し、アクターシステムにアクセスします。

Scalaの場合：

```scala
class MyComponent @Inject() (system: ActorSystem) {

}
```

Javaの場合：

```java
public class MyComponent {

    private final ActorSystem system;

    @Inject
    public MyComponent(ActorSystem system) {
        this.system = system;
    }
}
```

また、Play 2.6.xではAkka 2.5.xリリースシリーズが使用されるようになりました。必要に応じて、独自のコードを適用する方法については、 [2.4.xから2.5.xへのAkka移行ガイド](http://doc.akka.io/docs/akka/current/scala/project/migration-guide-2.4.x-2.5.x.html) をお読みください。

### 削除されたYaml API

私たちは `play.libs.Yaml` を削除しました。Play の中にもうそれを使用していなかったからです。 Play YAMLの統合をサポートする必要がある場合は、 `snakeyaml` を `build.sbt` に追加する必要があります。

```scala
libraryDependencies += "org.yaml" % "snakeyaml" % "1.17"
```

あなたのコードに以下のWrapperを作成します：

```java
public class Yaml {

    private final play.Environment environment;

    @Inject
    public Yaml(play.Environment environment) {
        this.environment = environment;
    }

    /**
     * Load a Yaml file from the classpath.
     */
    public Object load(String resourceName) {
        return load(
            environment.resourceAsStream(resourceName),
            environment.classLoader()
        );
    }

    /**
     * Load the specified InputStream as Yaml.
     *
     * @param classloader The classloader to use to instantiate Java objects.
     */
    public Object load(InputStream is, ClassLoader classloader) {
        org.yaml.snakeyaml.Yaml yaml = new org.yaml.snakeyaml.Yaml(new CustomClassLoaderConstructor(classloader));
        return yaml.load(is);
    }

}
```

またはScalaで：

```scala
class Yaml @Inject()(environment: play.api.Environment) {
  def load(resourceName: String) = {
    load(environment.resourceAsStream(resourceName), environment.classLoader)
  }

  def load(inputStream: InputStream, classLoader: ClassLoader) = {
    new org.yaml.snakeyaml.Yaml(new CustomClassLoaderConstructor(classloader)).load(inputStream)
  }
}
```

Playの代替DIライブラリに明示的に依存している場合、または独自のカスタムアプリケーションローダーを定義している場合は、変更は必要ありません。

Play DIサポートを提供するライブラリは、 `play.application.loader` 設定キーを定義する必要があります。外部DIライブラリが提供されていない場合は、 [ApplicationLoader](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/ApplicationLoader.html) をポイントしない限り、Playは起動を拒否します。

## 廃止予定の `play.Routes` を削除しました。

JavaScriptルータを作成するために使用された廃止予定のplay.Routesクラスが削除されました。新しいJavaまたはScalaヘルパーを使用する必要があります。

  * [ScalaでのJavascriptルーティング](https://www.playframework.com/documentation/2.6.x/ScalaJavascriptRouting)
  * [JavaでのJavascriptルーティング](https://www.playframework.com/documentation/2.6.x/JavaJavascriptRouter)


## 削除されたライブラリ

デフォルトのプレイ配布を少し小さくするために、いくつかのライブラリを削除しました。以下のライブラリは、もはやPlay 2.6の依存関係ではありませんので、使用する場合は手動でビルドに追加する必要があります。

### joda-time の削除

`java.time` APIを使用することをお勧めします。そのため、Playのコアからjoda-timeサポートを削除します。

PlayのScalaフォームライブラリには、いくつかのJodaフォーマットがありました。移行しない場合は、jodaFormsモジュールをbuild.sbtに追加できます。

```scala
libraryDependencies += jodaForms
```

そして、対応するオブジェクトをインポートします：

```scala
import play.api.data.JodaForms._
```

play-jsonでJodaサポートが必要な場合は、次の依存関係を追加できます。

```scala
libraryDependencies += "com.typesafe.play" %% "play-json-joda" % playJsonVersion
```

ここで、playJsonVersionは使用したいplay-jsonバージョンです。 Play 2.6.xはplay-json 2.6.xと互換性があります。 play-jsonは別のプロジェクトになりました(後述)。

```scala
import play.api.libs.json.JodaWrites._
import play.api.libs.json.JodaReads._
```

### Joda-Convertの削除

あなたがあなたのプロジェクトでそれをあなたのbuild.sbtに追加する必要があるならば、playはjoda-convertの内部使用をいくつか持っていました：

```scala
libraryDependencies += "org.joda" % "joda-convert" % "1.8.1"
```

### XercesImplの削除

XML処理の場合PlayはXerces XML Libraryを使用しました。現代のJVMは参照実装としてXercesを使用しているので、それを削除しました。プロジェクトが外部パッケージに依存している場合は、単純にbuild.sbtに追加することができます。

```scala
libraryDependencies += "xerces" % "xercesImpl" % "2.11.0"
```

### H2除去

以前のバージョンのPlayでは、H2データベースがプリインストールされていました。しかし、Playのコアを小さくするために、削除しました。 H2を使用する場合は、それをbuild.sbtに追加することができます：

```scala
libraryDependencies += "com.h2database" % "h2" % "1.4.193"
```

テストでのみ使用した場合は、Testスコープを使用することもできます。

```scala
libraryDependencies += "com.h2database" % "h2" % "1.4.193" % Test
```

依存関係を追加した後でもH2ブラウザは動作します。

### snakeyaml 除去

`play.libs.Yaml` を削除しました。したがって、 `snakeyaml` への依存関係は削除されました。まだ使用している場合は、 `build.sbt` に追加してください：

```scala
libraryDependencies += "org.yaml" % "snakeyaml" % "1.17"
```

[Yaml APIの削除に関する注意] も参照してください。

### Tomcat-servlet-apiの削除

`tomcat-servlet-api` は使用されていなかったので、Playで削除されました。まだ使用している場合は、 `build.sbt` に追加してください：

```scala
libraryDependencies += "org.apache.tomcat" % "tomcat-servlet-api" % "8.0.33"
```

## リクエスト属性

すべての要求オブジェクトに属性が含まれるようになりました。リクエスト属性は、リクエストタグの代わりとなります。タグは廃止され、属性にアップグレードする必要があります。属性はタグより強力です。属性を使用してオブジェクトを要求に格納できますが、タグはストリングの格納のみをサポートしています。

### リクエストタグの非推奨

タグは廃止されましたので、タグを使用してから属性を使用するように移行する必要があります。マイグレーションはかなり簡単です。

最も簡単な移行パスは、タグからString型の属性に移行することです。

以前のJava：

```java
// Getting a tag from a Request or RequestHeader
String userName = req.tags().get("userName");
// Setting a tag on a Request or RequestHeader
req.tags().put("userName", newName);
// Setting a tag with a RequestBuilder
Request builtReq = requestBuilder.tag("userName", newName).build();
```

これからのJava:

```java
class Attrs {
  public static final TypedKey<String> USER_NAME = TypedKey.<String>create("userName");
}

// Getting an attribute from a Request or RequestHeader
String userName = req.attrs().get(Attrs.USER_NAME);
String userName = req.attrs().getOptional(Attrs.USER_NAME);
// Setting an attribute on a Request or RequestHeader
Request newReq = req.withTags(req.tags().put(Attrs.USER_NAME, newName));
// Setting an attribute with a RequestBuilder
Request builtReq = requestBuilder.attr(Attrs.USER_NAME, newName).build();
```

以前のScala：

```scala
// Getting a tag from a Request or RequestHeader
val userName: String = req.tags("userName")
val optUserName: Option[String] = req.tags.get("userName")
// Setting a tag on a Request or RequestHeader
val newReq = req.copy(tags = req.tags.updated("userName", newName))
```

これからのScala:

```scala
object Attrs {
  val UserName: TypedKey[String] = TypedKey("userName")
}
// Getting an attribute from a Request or RequestHeader
val userName: String = req.attrs(Attrs.UserName)
val optUserName: [String] = req.attrs.get(Attrs.UserName)
// Setting an attribute on a Request or RequestHeader
val newReq = req.addAttr(Attrs.UserName, newName)
```

ただし、適切な場合は、StringタグをString以外の値を持つ属性に変換することをお勧めします。タグをString以外のオブジェクトに変換すると、いくつかの利点があります。まず、コードの型をより安全にします。これにより、コードの信頼性が向上し、理解しやすくなります。次に、属性に格納するオブジェクトには複数のプロパティを含めることができるため、複数のタグを単一の値に集約できます。第3に、タグを属性に変換すると、文字列の値をエンコードしてデコードする必要がなくなるため、パフォーマンスが向上する可能性があります。

```java
class Attrs {
  public static final TypedKey<User> USER = TypedKey.<User>create("user");
}
```

後のスカラ：

```scala
object Attrs {
  val UserName: TypedKey[User] = TypedKey("user")
}
```

### FakeRequest.withCookies を呼び出すと Cookies ヘッダーが更新されなくなりました

リクエストクッキーはリクエスト属性に格納されるようになりました。以前は、リクエストの [Cookie](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/Cookie.html) ヘッダ文字列に格納されていました。これは、クッキーが変更されるたびにヘッダーにクッキーをエンコードしてデコードする必要がありました。

クッキーがリクエスト属性に格納されるようになったので、クッキーを更新すると新しいクッキー属性は変更されますが、Cookie HTTPヘッダーは変更されません。これは、 `withCookies` を呼び出してヘッダを更新する場合にのみ、テストに影響します。

それでもなお古い動作が必要な場合は、 [Cookies.encodeCookieHeader](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/mvc/Cookies$.html#encodeCookieHeader(cookies:Seq[play.api.mvc.Cookie]):String) を使用してCookieオブジェクトをHTTPヘッダーに変換し、 `FakeRequest.withHeaders` でヘッダーを保存することができます。

### play.api.mvc.Security.username (Scala API)、session.username 変更

`play.api.mvc.Security.username`(Scala API)、 `session.username` 設定キーおよび依存アクションヘルパーは推奨されていません。 `Security.username` は、設定から `session.username` キーを取得するだけで、ユーザー名を取得するために使用されたセッションキーが定義されています。静的な動作が必要なため削除されました。同一または類似の動作を自分で実装するのはかなり簡単です。

`configuration.get[String]( "session.username")` を使用して、設定からユーザー名セッションキーを読み取ることができます。

`Authenticated(String => EssentialAction)` メソッドを使用している場合は、簡単に独自のアクションを作成して同様のことを行うことができます。

```scala
def AuthenticatedWithUsername(action: String => EssentialAction) =
  WithAuthentication[String](_.session.get(UsernameKey))(action)
```

UsernameKeyは、ユーザー名に使用するセッションキーを表します。

### リクエストセキュリティ(Java API)ユーザ名プロパティが属性になりました

Java Requestオブジェクトには、Security.AuthenticatedアノテーションがJavaアクションに追加されたときに設定される `username` プロパティが含まれています。 Play 2.6では、 `username` プロパティは廃止されました。 usernameプロパティのメソッドが更新され、 `Security.USERNAME` 属性にユーザー名が格納されます。 `Security.USERNAME` 属性を直接使用するようにコードを更新する必要があります。 Playの将来のバージョンでは、 `username` プロパティを削除します。

この変更の理由は、usernameプロパティが `Security.Authenticated` アノテーションの特別なケースとして提供されたためです。これで特別なケースは必要なくなりました。

既存のJavaコード：

```java
// Set the username
Request reqWithUsername = req.withUsername("admin");
// Get the username
String username = req1.username();
// Set the username with a builder
Request reqWithUsername = new RequestBuilder().username("admin").build();
```

アップデートされたJavaコード:

```java
import play.mvc.Security.USERNAME;

// Set the username
Request reqWithUsername = req.withAttr(USERNAME, "admin");
// Get the username
String username = req1.attr(USERNAME);
// Set the username with a builder
Request reqWithUsername = new RequestBuilder().putAttr(USERNAME, "admin").build();
```

### ルータタグは属性になりました

`Router.Tags.*` タグを使用した場合は、新しい [Router.Attrs.HandlerDef](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/routing/Router$$Attrs$.html#HandlerDef:play.api.libs.typedmap.TypedKey[play.api.routing.HandlerDef]) (Scala) または [Router.Attrs.HANDLER_DEF](https://www.playframework.com/documentation/2.6.x/api/java/play/routing/Router.Attrs.html#HANDLER_DEF) (Java)属性を使用するようにコードを変更する必要があります。 既存のタグは引き続き使用できますが、廃止され、今後のバージョンのPlayで削除されます。

この新しい属性には、現在タグ内にあるすべての情報を含む `HandlerDef` オブジェクトが含まれています。 現在のタグは、すべてHandlerDefオブジェクトのフィールドに対応します。

|Javaタグ名|Scalaタグ名|HandlerDefメソッド|
+-------+-----------+----------------+
|ROUTE_PATTERN | RoutePattern | path|
|ROUTE_VERB |  RouteVerb |verb|
|ROUTE_CONTROLLER |  RouteController |controller|
|ROUTE_ACTION_METHOD | RouteActionMethod |method|
|ROUTE_COMMENTS |  RouteComments |comments|

> 注：この変更の一環として、 `HandlerDef` オブジェクトが `play.core.routing` 内部パッケージから `play.api.routing` パブリックAPIパッケージに移動されました。

## play.api.libs.concurrent.Executionは推奨されていません

`play.api.libs.concurrent.Execution` クラスは、"現在の" アプリケーションのExecutionContextをプルするためにグローバルな可変状態を使用していたため、廃止されました。

以前に行った暗黙的な動作を指定する場合は、 [依存関係注入](https://www.playframework.com/documentation/2.6.x/ScalaDependencyInjection) を使用してコンストラクタに暗黙的に実行コンテキストを渡す必要があります。

```scala
class MyController @Inject()(implicit ec: ExecutionContext) {

}
```

[コンパイル時依存関係注入](https://www.playframework.com/documentation/2.6.x/ScalaCompileTimeDependencyInjection)を使用している場合はBuiltInComponentsから取得します。

```scala
class MyComponentsFromContext(context: ApplicationLoader.Context)
  extends BuiltInComponentsFromContext(context) {
  val myComponent: MyComponent = new MyComponent(executionContext)
}
```

ただし、一般的な場合でも実行コンテキストをインポートしたくない理由がいくつかあります。一般的なケースでは、アプリケーションの実行コンテキストは、アクションのレンダリングや、APIコールや I/O アクティビティのブロックに関係しないCPUバウンドアクティビティの実行に適しています。データベースを呼び出す場合やネットワーク呼び出しを行う場合は、独自のカスタム実行コンテキストを定義することができます。

カスタム実行コンテキストを作成するには、 [Custom ExecutionContext](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/libs/concurrent/CustomExecutionContext.html) を使用することをお勧めします。これは、Akkaディスパッチャシステム([java](http://doc.akka.io/docs/akka/2.5/java/dispatchers.html) / [scala](http://doc.akka.io/docs/akka/2.5/scala/dispatchers.html) )を使用して、エグゼキュータをコンフィグレーションで定義できるようにします。

独自の実行コンテキストを使用するには、 [CustomExecutionContext](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/libs/concurrent/CustomExecutionContext.html) 抽象クラスを `application.conf` ファイルのディスパッチャへのフルパスで拡張します。

```scala
import play.api.libs.concurrent.CustomExecutionContext

class MyExecutionContext @Inject()(actorSystem: ActorSystem)
 extends CustomExecutionContext(actorSystem, "my.dispatcher.name")
```

```scala
import play.libs.concurrent.CustomExecutionContext;
class MyExecutionContext extends CustomExecutionContext {
   @Inject
   public MyExecutionContext(ActorSystem actorSystem) {
     super(actorSystem, "my.dispatcher.name");
   }
}
```

必要に応じてカスタム実行コンテキストを注入します。

```scala
class MyBlockingRepository @Inject()(implicit myExecutionContext: MyExecutionContext) {
   // do things with custom execution context
}
```

カスタムスレッドプール設定の詳細については、 [ThreadPools](https://www.playframework.com/documentation/2.6.x/ThreadPools) ページを、CustomExecutionContextを使用する場合は [JavaAsync](https://www.playframework.com/documentation/2.6.x/JavaAsync) / [ScalaAsync](https://www.playframework.com/documentation/2.6.x/ScalaAsync) を参照してください。

## play.api.testヘルパーへの変更

推奨されない次のテストヘルパーは、2.6.xで削除されました。

  * `play.api.test.FakeApplication` は [`play.api.inject.guice.GuiceApplicationBuilder`](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/inject/guice/GuiceApplicationBuilder.html) に置き換えられました。
  * `play.api.test.Helpers.route(request)` は `play.api.test.Helpers.routes(app, request)` メソッドに置き換えられました。
  * `play.api.test.Helpers.route(request, body)` は [`play.api.test.Helpers.routes(app, request, body)`](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/test/Helpers$.html)メソッドに置き換えられました。

### Java API

  * `play.test.FakeRequest` が [RequestBuilder](https://www.playframework.com/documentation/2.6.x/api/java/play/mvc/Http.RequestBuilder.html) に置き換えられました
  * `play.test.FakeApplication` は `play.inject.guice.GuiceApplicationBuilder` に置き換えられました。  [play.test.Helpers.fakeApplication](https://www.playframework.com/documentation/2.6.x/api/java/play/inject/guice/GuiceApplicationBuilder.html) から新しいアプリケーションを作成できます。
  * `play.test.WithApplication `では、廃止予定の `provideFakeApplication` メソッドが削除されました。`provideApplication` メソッドを使用する必要があります。

## テンプレートヘルパーの変更

[views/helper/requireJs.scala.html](https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/helper/requireJs.scala.html) の requireJs テンプレートヘルパーは、 `Play.maybeApplication` を使用して設定にアクセスしました。

`requireJs` テンプレートヘルパーには、追加されたヘルパーのバージョンを使用する必要があるかどうかを示す追加パラメータ `isProd` が追加されています。

```
@requireJs(core = routes.Assets.at("javascripts/require.js").url, module = routes.Assets.at("javascripts/main").url, isProd = true)
```

## MIMEタイプマッピングへのファイル拡張の変更

ファイル拡張子のMIMEタイプへのマッピングは、 `reference.conf` に移動されているので、 `play.http.fileMimeTypes` 設定の下で、設定を通して完全にカバーされています。以前は、リストは `play.api.libs.MimeTypes` の下にハードコードされていました。

`play.http.fileMimeTypes` の設定は、トリプルクォートを単一の文字列として定義していることに注意してください。これは、複数のファイル拡張子に `c++` などの HOCON を壊す構文があるためです。

カスタムMIMEタイプを追加するには、 [HOCON文字列値の連結](https://github.com/typesafehub/config/blob/master/HOCON.md#string-value-concatenation) を使用します。

```
play.http.fileMimeTypes = ${play.http.fileMimeTypes} """
  foo=text/bar
"""
```

MIMEタイプを追加するために `mimetype.foo=text/bar` として定義された設定を可能にする構文があります。これは推奨されていません。上記の設定を使用することをお勧めします。

### Java API

`Http.Context.current().fileMimeTypes()` メソッドは、 `Results.sendFile` のフードの下にあり、ファイル拡張子からコンテンツタイプを検索するその他のメソッドがあります。移行は必要ありません。

### Scala API

`play.api.libs.MimeTypes` クラスが [play.api.http.FileMimeTypes](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/http/FileMimeTypes.html) インターフェイスに変更され、実装が [play.api.http.DefaultFileMimeTypes](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/http/DefaultFileMimeTypes.html) に変更されました。

ファイルまたはリソースを送信するすべての結果は、暗黙的に `FileMimeTypes` をとります。

```scala
implicit val fileMimeTypes: FileMimeTypes = ...
Ok(file) // <-- takes implicit FileMimeTypes
```

`FileMimeTypes` の暗黙のインスタンスは、便利なバインディングを提供するために、 `BaseController`(およびそのサブクラス `AbstractController` およびsubtrait `InjectedController`)によって `ControllerComponents` クラスによって提供されます。

```scala
class SendFileController @Inject() (cc: ControllerComponents) extends AbstractController(cc) {

  def index() = Action { implicit request =>
     val file = readFile()
     Ok(file)  // <-- takes implicit FileMimeTypes
  }
}
```

単体テストで完全に構成されたFileMimeTypesインスタンスを直接取得することもできます。

```scala
val httpConfiguration = new HttpConfigurationProvider(Configuration.load(Environment.simple)).get
val fileMimeTypes = new DefaultFileMimeTypesProvider(httpConfiguration.fileMimeTypes).get
```

またはカスタムのものを入手する：

```scala
val fileMimeTypes = new DefaultFileMimeTypesProvider(FileMimeTypesConfiguration(Map("foo" -> "text/bar"))).get
```

## デフォルトのフィルタ

Play には、設定によって定義された有効なフィルタのデフォルトセットが付属しています。 `play.http.filters` プロパティがnullの場合、デフォルトは `play.filters.enabled` 設定プロパティの完全修飾クラス名で定義されたフィルタをロードする [play.api.http.EnabledFilters](https://www.playframework.com/documentation/2.6.x/api/scala/play/api/http/EnabledFilters.html) になります。

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

  * [play.filters.csrf.CSRFFilter](https://www.playframework.com/documentation/2.6.x/api/scala/play/filters/csrf/CSRFFilter.html)
  * [play.filters.headers.SecurityHeadersFilter](https://www.playframework.com/documentation/2.6.x/api/scala/play/filters/headers/SecurityHeadersFilter.html)
  * [play.filters.hosts.AllowedHostsFilter](https://www.playframework.com/documentation/2.6.x/api/scala/play/filters/hosts/AllowedHostsFilter.html)

つまり、新しいプロジェクトでは、CSRF保護( [ScalaCsrf](https://www.playframework.com/documentation/2.6.x/ScalaCsrf) / [JavaCsrf](https://www.playframework.com/documentation/2.6.x/JavaCsrf) )、 [SecurityHeaders](https://www.playframework.com/documentation/2.6.x/SecurityHeaders) および [AllowedHostsFilter](https://www.playframework.com/documentation/2.6.x/AllowedHostsFilter) はすべて自動的に定義されます。

### デフォルトフィルタの効果

既定のフィルタは、プロジェクトに「デフォルトでセキュリティで保護された」構成を与えるように構成されています。

**これらのフィルタは有効にしておく必要があります。アプリケーションをより安全にするためです。**

既存のプロジェクトでこれらのフィルタを有効にしていない場合は、いくつかの設定が必要となり、関連するエラーや失敗に精通していない可能性があります。移行を支援するために、各フィルタ、そのフィルタ、必要な設定について説明します。

### CSRFFilter

CSRFフィルタについては [ScalaCsrf](https://www.playframework.com/documentation/2.6.x/ScalaCsrf) と [JavaCsrf](https://www.playframework.com/documentation/2.6.x/JavaCsrf) で説明しています。これは、POSTリクエストでチェックされるフォームにCSRFトークンを追加することにより、 [クロスサイト要求偽造攻撃](https://en.wikipedia.org/wiki/Cross-site_request_forgery) から保護します。

#### デフォルトで有効になっている理由

CSRFは非常に一般的な攻撃であり、実装に必要なスキルはほとんどありません。 Playを使用してCSRF攻撃の例を見ることができます(https://github.com/Manc/play-scala-csrf)。

#### どのような変更が必要ですか？

`CSRF.formField` などのCSRFフォームヘルパを使用しない既存のプロジェクトから移行する場合は、CSRFフィルタのPUTおよびPOSTリクエストに「403 Forbidden」が表示されることがあります。

`CSRF.formField` をフォームテンプレートに追加するとエラーが解決されます。AJAXでリクエストを作成する場合は、HTMLページにCSRFトークンを置き、 `Csrf-Token` ヘッダーを使用して要求に追加できます。

この動作を確認するには、 `logback.xml` に `<logger name = "play.filters.csrf" value = "TRACE" />` を追加してください。

また、 Play の SameSite Cookie を有効にして、CSRF攻撃に対する追加防御を提供することもできます。

### SecurityHeadersFilter

[SecurityHeadersFilter](https://www.playframework.com/documentation/2.6.x/SecurityHeaders) は、リクエストに余分なHTTPヘッダーを追加することで、 [クロスサイトスクリプティング](https://en.wikipedia.org/wiki/Cross-site_scripting) と [クリックジャック攻撃](https://en.wikipedia.org/wiki/Clickjacking) を防ぎます。

#### デフォルトで有効になっている理由

ブラウザベースの攻撃は非常に共通しています。セキュリティヘッダーは、これらの攻撃を阻止するための深い防御を提供します。

#### どのような変更が必要ですか？

デフォルトの "Content-Security-Policy" の設定は非常に厳密です。最も有用な設定を見つけるには、それを試す必要があります。コンテンツセキュリティポリシーの設定では、Javascriptとリモートフレームがブラウザにどのように表示されるかが変更されます。 **Content-Security-Policyヘッダーを変更するまで、埋め込まれたJavascriptまたはCSSはWebページに読み込まれません。**

有効にしたくない場合は、次のようにContent-Security-Policyを無効にすることができます。

```
play.filters.headers.contentSecurityPolicy=null
```

[CSP-Useful](https://github.com/nico3333fr/CSP-useful) は、一般的な Content-Security-Policy の優れたリソースです。すべてのリクエストにカスタムCSPナンスを追加するなど、埋め込まれたJavascriptに対する他の潜在的な解決策があることに注意してください。

他のヘッダーは侵入性が低く、プレーンなWebサイトで問題を引き起こす可能性は低いですが、シングルページアプリケーションでCookieやレンダリングの問題が発生する可能性があります。 Mozillaには、URLのヘッダ名を使用して、各ヘッダを詳細に記述するドキュメントがあります。たとえば、X-Frame-Optionsの場合は https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options に行きます。

```
play.filters.headers {

    # The X-Frame-Options header. If null, the header is not set.
    frameOptions = "DENY"

    # The X-XSS-Protection header. If null, the header is not set.
    xssProtection = "1; mode=block"

    # The X-Content-Type-Options header. If null, the header is not set.
    contentTypeOptions = "nosniff"

    # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set.
    permittedCrossDomainPolicies = "master-only"

    # The Content-Security-Policy header. If null, the header is not set.
    contentSecurityPolicy = "default-src 'self'"

    # The Referrer-Policy header. If null, the header is not set.
    referrerPolicy = "origin-when-cross-origin, strict-origin-when-cross-origin"

    # If true, allow an action to use .withHeaders to replace one or more of the above headers
    allowActionSpecificHeaders = false
}
```

### AllowedHostsFilter

AllowedHostsFilter は、許可されたホストのホワイトリストを追加し、ホワイトリストと一致しないホストを持つすべての要求に 400(Bad Request) 応答を送信します。

#### デフォルトで有効になっている理由

DNSリバインディング攻撃は、開発者のPlayのインスタンスに対して使用できるため、開発で使用する重要なフィルタです。短期間のDNS再バインドがlocalhost上で動作するサーバを攻撃する方法の例については、[Rails Webconsole DNS Rebinding](https://benmmurphy.github.io/blog/2016/07/11/rails-webconsole-dns-rebinding/) を参照してください。

#### どのような変更が必要ですか？

localhost 以外のアプリケーションでPlayアプリケーションを実行している場合は、 AllowedHostsFilter を設定して、接続先の　ホスト名/IP を特に許可する必要があります。通常、開発環境ではlocalhostで実行されますが、ステージングや本番環境ではリモートで実行されるため、環境を変更するときに注意する必要があります。

```
play.filters.hosts {
  # Allow requests to example.com, its subdomains, and localhost:9000.
  allowed = [".example.com", "localhost:9000"]
}
```

### フィルタに追加する

デフォルトリストに追加するには、 `+=` ：

```
play.filters.enabled+=MyFilter
```

`play.api.http.DefaultHttpFilters` を拡張して独自のフィルタを定義した場合、 `EnabledFilters` とコード内の独自のリストを組み合わせることもできます。これまでにプロジェクトを定義していたとしても、通常どおりに機能します。

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

### デフォルトフィルタのテスト

いくつかのフィルターが有効になっているため、すべてのテストが合格し、要求が有効であることを確認するために機能テストを少し変更する必要があります。たとえば、 `Host` HTTPヘッダーが `localhost` に設定されていない要求は AllowedHostsFilter を渡さず、代わりに 400 Forbidden 応答を返します。

#### AllowedHostsFilterを使用したテスト

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

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

```scala
RequestBuilder request = new RequestBuilder()
        .method(GET)
        .header(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.FakeRequest` を `withCSRFToken` メソッドで埋められます：

```scala
import play.api.test.CSRFTokenHelper._

class UserControllerSpec extends PlaySpec with GuiceOneAppPerTest {
  "UserController GET" should {

    "render the index page from the application" in {
      val controller = app.injector.instanceOf[UserController]
      val request = FakeRequest().withCSRFToken
      val result = controller.userGet().apply(request)

      status(result) mustBe OK
      contentType(result) mustBe Some("text/html")
    }
  }
}
```

Java APIでは、これは `play.mvc.Http.RequestBuilder` インスタンスで `CSRFTokenHelper.addCSRFToken` を呼び出すことによって行われます。

```java
requestBuilder = CSRFTokenHelper.addCSRFToken(requestBuilder);
```

### デフォルトのフィルタを無効にする

デフォルトのフィルタを無効にする最も簡単な方法は、 `application.conf` に手動でフィルタのリストを設定することです。

```
play.filters.enabled = []
```

これは、デフォルトのフィルタを使用したくない機能テストがある場合に便利です。

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

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

あるいは `EnabledFilters` で置換

```
play.http.filters = play.api.http.NoHttpFilters
```

`GuiceApplicationBuilder` を含む機能テストを作成していて、デフォルトのフィルタを無効にしたい場合は、 `configure` を使用してフィルタをすべて無効にすることができます。

```scala
GuiceApplicationBuilder().configure("play.http.filters" -> "play.api.http.NoHttpFilters")
```

## コンパイル時のデフォルトフィルタ

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

これは、 `BuiltInComponents` トレイトに `httpFilters` メソッドが含まれていて、抽象化されたままであることを意味します。

```scala
trait BuiltInComponents {

  /** A user defined list of filters that is appended to the default filters */
  def httpFilters: Seq[EssentialFilter]
}
```

フィルタのデフォルトリストは `play.filters.HttpFiltersComponents` で定義されています：

```scala
trait HttpFiltersComponents
     extends CSRFComponents
     with SecurityHeadersComponents
     with AllowedHostsComponents {

   def httpFilters: Seq[EssentialFilter] = Seq(csrfFilter, securityHeadersFilter, allowedHostsFilter)
}
```

ほとんどの場合、 `HttpFiltersComponents` をミックスして独自のフィルタを追加する必要があります：

```scala
class MyComponents(context: ApplicationLoader.Context)
  extends BuiltInComponentsFromContext(context)
  with play.filters.HttpFiltersComponents {

  lazy val loggingFilter = new LoggingFilter()
  override def httpFilters = {
    super.httpFilters :+ loggingFilter
  }
}
```

リストから要素をフィルタリングする場合は、次の操作を実行できます。

```scala
class MyComponents(context: ApplicationLoader.Context)
  extends BuiltInComponentsFromContext(context)
  with play.filters.HttpFiltersComponents {
  override def httpFilters = {
    super.httpFilters.filterNot(_.getClass == classOf[CSRFFilter])
  }
}
```

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

デフォルトのフィルタを無効にするには、 `play.api.NoHttpFiltersComponents` をミックスインします：

```
class MyComponents(context: ApplicationLoader.Context)
   extends BuiltInComponentsFromContext(context)
   with NoHttpFiltersComponents
   with AssetsComponents {

  lazy val homeController = new HomeController(controllerComponents)
  lazy val router = new Routes(httpErrorHandler, homeController, assets)
}
```

## JWTサポート

Play の Cookie エンコーディングが JSON Webトークン(JWT) を使用するように切り替わりました。 JWTには、HMAC-SHA-256による自動署名や、セッションクッキーが指定された時間枠外で再利用できないことを保証する自動「前回」および「期限切れ」日付チェックのサポートなど、多くの利点があります。

詳細は、[「セッションCookieの設定」](https://www.playframework.com/documentation/2.6.x/SettingsSession)ページを参照してください。

### フォールバッククッキーのサポート

PlayのCookieエンコーディングは、JWTでエンコードされたCookieを読み込み、JWTの解析が失敗した場合にURLでエンコードされたCookieを読み取ろうとする「フォールバック」Cookieエンコードメカニズムを使用しているため、既存のセッションCookieをJWTに安全に移行できます。この機能は `FallbackCookieDataCodec` トレイトにあり、 `DefaultSessionCookieBaker` と `DefaultFlashCookieBaker` を利用しています。

### レガシーサポート

JWTでエンコードされたクッキーを使用することはシームレスでなければなりませんが、必要に応じて `application.conf` ファイルの `play.api.mvc.LegacyCookiesModule` に切り替えることでURLエンコードされたクッキーエンコーディングに戻すことができます：

```
play.modules.disabled+="play.api.mvc.CookiesModule"
play.modules.enabled+="play.api.mvc.LegacyCookiesModule"
```

### カスタムCookieBakers

カスタム Cookie が `CookieBaker[T]`トレイトを使用して Play で使用されている場合は、カスタム Cookie ベーカーに必要なエンコーディングの種類を指定する必要があります。

The `encode` and `decode` methods that `Map[String, String]` to and from the format found in the browser have been extracted into `CookieDataCodec` 。 `FallbackCookieDataCodec` 、 `JWTCookieDataCodec` 、または `UrlEncodedCookieDataCodec` の3つの実装があります。それぞれHMAC、JWT、または「JWTの書き込みコードまたはJWTの読み取り」コーデックでURLエンコードされています。

また、`JWTConfigurationParser` を使用して構成へのパスを使用して `JWTConfiguration` case class を提供するか、またはデフォルトの `JWTConfiguration()` を使用する必要があります。

```scala
@Singleton
class UserInfoCookieBaker @Inject()(service: UserInfoService,
                                    val secretConfiguration: SecretConfiguration)
  extends CookieBaker[UserInfo] with JWTCookieDataCodec {

  override val COOKIE_NAME: String = "userInfo"

  override val isSigned = true

  override def emptyCookie: UserInfo = new UserInfo()

  override protected def serialize(userInfo: UserInfo): Map[String, String] = service.encrypt(userInfo)

  override protected def deserialize(data: Map[String, String]): UserInfo = service.decrypt(data)

  override val path: String = "/"

  override val jwtConfiguration: JWTConfiguration = JWTConfigurationParser()
}
```

## 非推奨のFuturesメソッド

次の `play.libs.concurrent.Futures` 静的メソッドは廃止予定です：

  * `timeout(A value, long amount, TimeUnit unit)`
  * `timeout(final long delay, final TimeUnit unit)`
  * `delayed(Supplier<A> supplier, long delay, TimeUnit unit, Executor executor)`

依存関係が挿入された `Futures` のインスタンスを代わりに使用する必要があります。

```java
class MyClass {
    @Inject
    public MyClass(play.libs.concurrent.Futures futures) {
        this.futures = futures;
    }

    CompletionStage<Double> callWithOneSecondTimeout() {
        return futures.timeout(computePIAsynchronously(), Duration.ofSeconds(1));
    }
}
```

## 更新されたライブラリ

### Netty 4.1

Nettyは [バージョン4.1](http://netty.io/news/2016/05/26/4-1-0-Final.html) にアップグレードされました。これは主に、バージョン4.0が [スタンドアローンモジュールへのplay-wsの移行](https://www.playframework.com/documentation/2.6.x/WSMigration26) によって網羅されていたために可能でした。したがって、 [Netty Server](https://www.playframework.com/documentation/2.6.x/NettyServer) と Netty 4.0に依存するライブラリを使用している場合は、ライブラリの新しいバージョンにアップグレードするか、 [Akka Server](https://www.playframework.com/documentation/2.6.x/AkkaHttpServer) の使用を開始することをお勧めします。

何らかの理由でNettyクラスを直接使用している場合は、 [コードをこの新しいバージョンに適合させる](http://netty.io/wiki/new-and-noteworthy-in-4.1.html) 必要があります。

### FluentLeniumとSelenium

FluentLeniumライブラリはバージョン 3.2.0 にアップデートされ、Selenium はバージョン [3.3.1](https://seleniumhq.wordpress.com/2016/10/13/selenium-3-0-out-now/) にアップデートされました([ここで変更履歴をご覧ください](https://raw.githubusercontent.com/SeleniumHQ/selenium/master/java/CHANGELOG))。以前に Selenium の WebDriver API を使用していた場合は、何もするべきではありません。詳細については、 [この](https://seleniumhq.wordpress.com/2016/10/04/selenium-3-is-coming/) アナウンスを確認してください。
FluentLenium ライブラリを使用していた場合は、テストを再開するためにいくつかの構文を変更する必要があります。あなたのコードを変更する方法の詳細については、FluentLeniumの [移行ガイド](http://fluentlenium.org/migration/from-0.13.2-to-1.0-or-3.0/) を参照してください。

### HikariCP

HikariCP が更新され、新しい設定が導入されました： `initializationFailTimeout` 。この新しい構成は、現在廃止されている `initializationFailFast` の代わりに使用する必要があります。この新しい設定の使い方を理解するには、 [HikariCPの変更ログ](https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES) と [`initializationFailTimeout`のドキュメント](https://github.com/brettwooldridge/HikariCP#infrequently-used) を参照してください。

## その他の構成の変更

いくつかの設定変更があります。通常、古い設定パスは動作しますが、使用すると、実行時に非推奨警告が出力されます。変更されたキーの概要を以下に示します。

|古いキー | 新しいキー  |
|-------+----------+
|play.crypto.secret  |  play.http.secret.key|
|play.crypto.provider   |  play.http.secret.provider|
|play.websocket.buffer.limit  |  play.server.websocket.frame.maxLength|