Google App Engine/JavaでのScala/Liftアプリケーション開発(後編)
GoogleサービスのAPIを利用してアプリケーションを構築
ダウンロード サンプルファイル (19.1 KB)
ユーザー認証の設定
通常、認証が必要なアプリケーションでは、ユーザーが認証されているかチェックし、ログイン画面を表示する処理が必要です。
GoogleアカウントAPIを利用した認証では、アプリケーションがAPIを利用し、認証状態をチェックしてログイン画面へリダイレクトさせる方法と、web.xmlに認証が必要なuriを定義して自動的に処理させる方法の2通りがあります。
本稿では、後者のweb.xmlへの設定により認証を行う方法を利用します。
LiftFilterを拡張する
ローカル開発環境でGoogleアカウントAPIを利用した認証を行う場合、ログイン画面のURLは"http://localhost:8080/_ah/login"のようなURLになります。この"/_ah/"で始まるURLをLiftが処理しないように、Liftで提供されているLiftFilterクラスを拡張する必要があります。
"src/main/scala/bootstrap/liftweb/"ディレクトリに、"LiftFilterForAppEngine.scala"というファイル名で以下の内容のソースコードを新規に作成します。
package bootstrap.liftweb
import net.liftweb.http.{Req, LiftRules}
class LiftFilter extends net.liftweb.http.LiftFilter {
override def isLiftRequest_?(session: Req): Boolean =
!session.request.uri.startsWith("/_ah/") && super.isLiftRequest_?(session)
}
このLiftFilterクラスは、LiftFilterクラスが持つisLiftRequest_?関数をオーバーライドして、"/_ah/"で始まるリクエストはLiftで処理しないようにしてあります。
web.xmlへの設定
"src/main/webapp/WEB-INF"にある"web.xml"を修正します。太字の部分は追加してください。
<web-app>
<filter>
<filter-name>LiftFilter</filter-name>
<display-name>Lift Filter</display-name>
<description>The Filter that intercepts lift calls</description>
<filter-class>bootstrap.liftweb.LiftFilter</filter-class> *1
</filter>
...中略...
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern> *2
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name> *3
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<url-pattern>/mailSender/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
</web-app>
*1では、先ほど用意したLiftFilterクラスを利用するようにServletFilterの設定を変更しておきます。
*2が、認証を必要とするurlのパターンです。今回はすべてのurlで認証が必要なように設定しています。*3は、認証に必要なロールです。"*"は、Googleアカウントを持つユーザーなら誰でも認証を行えるような設定です。このロールを"admin"に指定すると、アプリケーションの管理者のみがアクセスできるように制限することが可能です。
2つ目のsecurity-constraintタグで指定されているのは、この後解説するリマインダメール送信の際に使用する定義なので、ここで同時に追加しておきます。
ログアウトリンクの追加
ログインへの誘導は自動で行われますが、ログアウトはユーザーが明示的に行うので、ログアウト用のリンクを用意しておく必要があります。
ログアウト処理自体は、GoogleアカウントAPIでログアウト用URLを取得してリダイレクトするだけです。リダイレクトだけのためにテンプレートを用意するのは手間です。ここでは、テンプレートを用意しないで処理できるようにしておくため、LiftViewという仕組みを利用してログアウトさせます。
LiftViewは、テンプレートの代わりに直接XHTMLを関数から戻り値として返すことができる仕組みです。LiftViewトレイトを継承したクラスをviewディレクトリに用意しておくだけです。
"src/main/scala/demo/view"ディレクトリに、Logout.scalaを以下の内容で作成します。
package demo.view
...中略...
class Logout extends LiftView{
def dispatch = Map("index" -> logout _ ) *1
def logout = {
val userService = UserServiceFactory.getUserService *2
redirectTo( userService.createLogoutURL("/") ) *3
}
}
このLogoutクラスは、dispatch関数(*1)でURLに対してどの関数を処理に割り当てるかを定義しています。今回は"/logout"というリンクを処理させたいため、index(/に対応)をlogout関数に割り当てています。
logout関数は、GoogleアカウントAPIでUserServiceを取得し(*2)、UserServiceのcreateLogoutURLメソッドを呼び出して得られるURLにリダイレクトさせています。
"/logout"というURLをLogoutクラスに処理させるために、Boot.scalaにSiteMapの定義を追加します。この定義は、通常のテンプレートのURLの指定がViewのクラス名に変わっただけです。
val entries = Menu(Loc("Home", List("index"), "Topページ")) ::
Menu(Loc("Save", List("save"), "イベントを作る")) ::
Menu(Loc("Logout", List("logout"), "ログアウト")) :: Nil
動作確認
ここまで設定して、mvn packageコマンドでコンパイルし、dev_appserverコマンドで開発サーバを起動して"http://localhost:8080"にアクセスすると、次のような開発環境用のログイン画面が表示されます。

ここで入力する内容は、任意のユーザーアカウント名で構いません。実際に存在しないアカウント名でも認証されたことになります。チェックボックスにチェックしておくと、管理者としてログインしたものとして扱われます。
この記事は参考になりましたか?
- Google App Engine/JavaによるScala/Liftアプリケーション開発連載記事一覧
-
- Google App Engine/JavaでのScala/Liftアプリケーション開発(...
- Google App Engine/JavaによるScala/Liftアプリケーション開発...
- この記事の著者
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
WINGSプロジェクト 尾崎 智仁(オザキ トモヒト)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
