Play framework 2.3 for Scalaで、認証してみる
注:2015/7に書いた記事です。
どうもこんにちは、えみーです。
Play framework 2.3 for Scalaで、認証してみよう!と思ったんですが、公式ドキュメント系がイマイチ見つけられず…ちょっと試行錯誤したので、おぼえがき程度に書いておきます。
認証の方針
先のセッション管理でも参考にさせていただいた、Javaでの記事を参考にて考えました。
参考:ステートレスなPlay2でログイン状態を管理する - C Sharpens you up
異なる点は以下。
- クッキーは、Playのセッションメソッドを通して使う(Playのセッションはクライアントサイドのクッキーとして実現されている)
- Scalaである
参考にした記事では、play.mvc.Security.Authenticatorをextendsしているんですが、play.mvc._ はJava用のAPIなので、Scala用のAPIであるplay.api.mvc.Securityからなんやかんやしたいです。
というわけで、Play framework 2.0.4のドキュメントで以下のものがあったので、参考にして、認証用のtraitを作ります。
Scala Security - 2.0.4
(2.3.x用の、上記に該当するページが見つけられず…。ただ、APIを確認すると、play.api.mvc.Security.Authenticatedメソッドは2.3.xでも存在してます。また、APIのAuthenticatedメソッドの解説に、認証用trait及びそれを使ったController内のアクション記載の説明もあるので、そのまま参考にしてみます。play.api.mvc.SecurityのAPIドキュメント)
あと、Playのセッションではタイムアウトは、2.3以降はできるようになったようです。(参考:Migration23 - 2.3.x)
とすると、「セッションが切れたかどうか」は、単純にセッションの有無で判断してもよさそうです。
もちろん、二重ログインがどうとか他の問題はありますが、そのあたりはいったん置いておいきます。。
やったこと
以下に実際にやったものの覚書を置いておきます。
- セッションタイムアウトの設定
- Authenticateチェック用のトレイト
- 認証を必要とする画面表示やアクション(コントローラ)
セッションタイムアウトの設定
そんなわけで、まずセッションクッキーの名前「PLAYSESSION」と、タイムアウトの設定を30分にします。
conf/application.conf
session.cookieName=PLAYSESSION session.maxAge=30m
Authenticateチェック用のtrait
Authenticator.scala
package controllers import play.api._; import play.api.mvc._; trait Secured{ // セッションがあるとき、取得する値。 getの中身は欲しいキーを入れる。 def username(request: RequestHeader) = request.session.get(Security.username) // セッションがないときのふるまい。例は新規セッションを作ってログインページを表示する。 def onUnauthorized(request : RequestHeader) = { Results.Ok(views.html.login()).withNewSession } // セッションのあるないをチェックしてからActionを実行するためのメソッド。Controllerで使用する。 def withAuth(f: => String => Request[AnyContent] => Result) = { Security.Authenticated(username, onUnauthorized) { user => Action(request => f(user)(request)) } }
認証を必要とする画面表示やアクション(コントローラ)の記述
Sample.scala
package controllers import play.api._ import play.api.mvc._ object SampleController extends Controller with controllers.Secured { // ログインしていない場合のアクション def showTop = Action { implicit request => Ok("Please login!") } // ログインしている場合のアクション def showMembersPage = withAuth { username => implicit request => Ok("Hello, " + username + "!") } }