Created
July 23, 2013 04:06
-
-
Save rhiguchi/6059786 to your computer and use it in GitHub Desktop.
Play Framework で Basic 認証を行うアクションのミックスイン ref: http://qiita.com/flo_jack/items/257fe8b0cf93151f8a3d
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controllers | |
import play.api._ | |
import play.api.mvc._ | |
/** | |
* 管理者のアカウントを取り扱うモジュール | |
*/ | |
trait AdminSecure { | |
import play.api.mvc.Results._ | |
private[this] val accounts = Map("admin" -> "password") | |
protected val basicRealm = "(my realm)" | |
/** ユーザー名とパスワードが一致するかを返します */ | |
protected def checkAccount(userName: String, password: String) = | |
accounts.get(userName).filter(_ == password).nonEmpty | |
/** | |
* 認証を確認して実行するアクション | |
*/ | |
object AdminAction { | |
private val AUTHORIZATION = "authorization" | |
private val WWW_AUTHENTICATE = "WWW-Authenticate" | |
private def realm = "Basic realm=\"%s\"".format(basicRealm) | |
def apply(f: AuthenticatedRequest[AnyContent] => Result): Action[AnyContent] = | |
apply(BodyParsers.parse.anyContent)(f) | |
def apply[A](p: BodyParser[A])(f: AuthenticatedRequest[A] => Result) = Action(p) { request => | |
request.headers.get(AUTHORIZATION) match { | |
case Some(BasicAuthorization(name, pw)) if checkAccount(name, pw) => | |
f(new AuthenticatedRequest(name, request)) | |
case _ => Unauthorized("need admin login").withHeaders(WWW_AUTHENTICATE -> realm) | |
} | |
} | |
/** | |
* Basic 認証の値の取り扱い | |
*/ | |
private object BasicAuthorization { | |
private val basicPefix = "Basic " | |
private val AUTHORIZATION_PARAMS = """([^:]+?):(.+)""".r | |
/** | |
* Base64 エンコードで文字列化された Basic 認証値を、ユーザー名とパスワードに分解して返します | |
* | |
* @param auth Base64 エンコード文字列 | |
* @return 名前とパスワード | |
*/ | |
private[this] def decode(auth: String): Option[(String, String)] = { | |
val d = javax.xml.bind.DatatypeConverter.parseBase64Binary(auth) | |
new String(d, "utf-8") match { | |
case AUTHORIZATION_PARAMS(username, password) => Some(username, password) | |
case _ => None | |
} | |
} | |
/** | |
* WWW-Authenticate ヘッダの値から、ユーザー名とパスワードを取り出します。 | |
* | |
* @param authorization WWW-Authenticate ヘッダ値。ヘッダの名前は含まない。 | |
* @return 名前とパスワード | |
*/ | |
def unapply(authorization: String): Option[(String, String)] = authorization match { | |
case s if s startsWith basicPefix => decode(s drop basicPefix.length) | |
case _ => None | |
} | |
} | |
/** 認証されて実行するリクエスト */ | |
class AuthenticatedRequest[A] private[controllers] | |
(val userName: String, request: Request[A]) extends WrappedRequest(request) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controllers | |
import play.api._ | |
import play.api.mvc._ | |
object Application extends Controller with AdminSecure { | |
def adminHome = AdminAction { implicit request => | |
Ok("Welcome back, " + request.userName) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment