第10回はログイン認証です。Authenticateionがあったんだけど、2.3系にはログイン認証に関するページが存在しなかったので、色々見ながら最低限それっぽく動くところまでをやってみました。GitHub2.2系のdocumentには、@Security.Authenticatedでリクエストの認証をやってるっぽいけど、2.3ではどうなんでしょう。deprecatedなやり方なのかな?とか不安に思ったんですが、2.3系のdocumentでもページこそ存在してないけど、こんな記述がありました。information.という記述があったから、deprecatedではないだろうと判断しました。2.2系のチュートリアル見ながら2.3系でも同じことができるか検証していきます。毎度のことですが、コマンドラインならひな形を作ります。ログイン認証が必要なECサイトを作るイメージで名前はplay-shopとでもしておきますか。runで、localhost:9000でいつもの例のやつが見れます。ログインに使うためのモデルを作る何はともあれ、モデルがなきゃ始まりません。こんな感じで、app/models/User.javaを作ります。今回はめんどいので、JPAじゃなくEBeanを使います。ユーザー名が入力されてないとエラーになるようなアノテーションを入れています。);}あとはDBが起動するように、conf/application.confをいじって、以下のところコメントを外しておきます。コントローラーに処理を書いていくconf/routesはこんな感じです。2.2のチュートリアルとは違うかもしれませんが、その辺は適当です。/loginにアクセスして、ユーザー名とパスワード入力して、送信先は、POSTの/loginで、認証できたら、/へリダイレクトするって感じです。controllers.Application.authenticate()そして、コントローラーに処理を書いていきます。app/controllers/Application.javaを以下のように編集していきます。ok(login.render(Form.form(User.class)));で、Formを渡しつつ、login.scala.htmlをレンダリングするようにします。POSTされたときのauthenticateメソッドを作って、Formのバリデーションに引っかかったらログインページに戻す。正常ならセッションにユーザー名をセットしてトップにリダイレクトっていう流れです。あとは、loginページを作る必要があります。app/views/login.scala.htmlを作って、見た目になんの工夫もなくただ単にユーザー名とパスワードのフォームを配置した。@inputPasswordなんてヘルパーも用意されてるのね。}</body></html>最後にもともとあったサンプルページをちょっと修正。world表示するだけのページに以下のように書き換えた。world</p></body></html>これで、/loginにアクセスしてみると、、って感じで、フォームが出てきて、名前を入力しないとエラーになって、/loginページに戻される。worldが表示されるってアプリケーションができました。ふむふむ、ひとまずそれっぽい感じになった。認証になっていないので、作っていきます。認証をDBの値から取得して突き合わせるようにするまず、テストユーザー作るために、普通はありえないけど、login.scala.htmlページにユーザー作ってくれるリンクを作成する。ユーザー名はテキトーで、admin、パスワードはpassword123ってことで。controllers.Application.addUser()コントローラーに処理を書く。adminって名前のユーザーを検索してなければ、ユーザーを作成します。}実際の登録処理は、モデルに書くので、User.javaにcreateメソッド作る。モデルのUser.javaに以下のようにvalidate()メソッドを書く。これは、playでは特別なメソッドで、これを書いておくとフォームのバリデーションを適用してくれる。formのドキュメントにも書いてありますね。password)メソッドを自前で作る。ユーザー名とパスワードが存在すれば、authenticateはtrueを返すので、validate()メソッドはnullを返す。これは、validationした結果問題はありませんよみたいなことです。エラーがある場合は、エラーメッセージを返しています。password)の方は、playにとって意味のあるメソッドじゃなくて適当に作ったやつ。教えてて思ったのは、このあたりのフレームワークにとって特別な存在なのか、どうでもいいものなのかっていう判断が初めての人には難しいのかも。これで以下のところまでいけるはず。loginページにアクセステストユーザーを作成admin、password123以外だとログインできなくて/loginに戻ってくるテストユーザーの情報を入れればログインして/にリダイレクトただ、これだと、logoutできないのと、login失敗したときのエラーメッセージがない。controllers.Application.logout()index.scala.htmlにlogoutのリンク作る。</ul></body>コントローラーにはlogoutメソッド作る。session().clear()ってやれば、logoutできます。loginForm.get().name);をクリアしてるってこと。}んで、エラーメッセージを表示するために、login.scala.htmlの好きなとこにこれを追加する。}hasGlobalErrorsというのはFormクラスのメソッドで、モデルで追加したvalidate()メソッドで返したエラーが存在するかが分かるので、これでエラーメッセージが出る。これで、データベースの値で認証できつつ、エラーメッセージ、ログアウトが実装できました。これを認証必要なページにします。認証必要というのは、認証しないと見れないということです。ctx)で、ログイン成功したときの処理。ここは、セッションに入れた値を返すようにする。ctx)は認証していないときの処理でloginページにリダイレクトするって処理。ここまでいったら、あとは、こんな風にコントローラーのところに、@Security.Authenticated(Secured.class)をアノテーション書くだけで、好きなアクションに認証がつけられる。}こうすると、logoutしたあとに、/に直接アクセスしても認証してないということで、/loginページに行くことが確認できると思います。パスワードの暗号化かなり認証っぽくなりましたが、最後に、このままでは、パスワードが平文でDBに格納されてしまいます。DBの管理者や開発者、クラックされたときにだだ漏れです。そんなことはWebアプリケーションではありえないので、これを暗号化します。0.3mを使おうってことらしい。stackoverflow見てても、jbcryptを使ってるっぽいからこれに決めた。build.sbtにjbcryptの依存関係を追加します。"0.3m")User.javaのauthenticateメソッドと、ユーザー作成createメソッドのところをjbcryptを使うように修正。authenticateメソッドは、今まで、passwordをwhere句で文字列として比較してたけど、BCryptのcheckpwメソッドを使うようだ。あとは、ユーザーを作成する方で、createメソッドで、パスワードを暗号化して保存するように変えます。}sbtを再読み込みしたいのと、DBを一旦クリアしたいので、activatorをexitして、再度立ち上げてrun。/loginページで、テストユーザーを作成してからログインしてみれば、ログインできる。ログアウトしたあと、パスワードを間違えればちゃんとログインできてないことも確認できる。今回はメモリ上のDBを使っているので、登録されているレコードを見るのに、h2-browserというのを使います。コンソールで、runをしてるアプリケーションを一旦停止して、そのまま以下のコマンドを打つ。userしてみれば、パスワードのところに暗号化された文字列が入っていることが確認できます。まとめrailsとかだと、gemを見つけてきてそれでやるってのが普通だからどれが一番ナウいのか?を見極めるのが難しいんだけど、playにはそれっぽいクラスが最初から用意されてて、初心者には嬉しい感じ。OAuthとか別の認証もとりいれようと思ったらライブラリ入れた方がよいんだろうけど。思ったより簡単でした。いうか、自分がだんだんplayに慣れてきたからってのもあるけど。第11回は、リレーションを持つデータのCRUDアプリケーションについてです。ツイートはてなブログをはじめよう!masato47744さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。