|
Play Framework/Scala example source code file (Security.scala)
The Security.scala Play Framework example source code
/*
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package play.api.mvc
import play.api._
import play.api.mvc.Results._
import play.api.libs.iteratee._
import scala.concurrent.Future
/**
* Helpers to create secure actions.
*/
object Security {
/**
* Wraps another action, allowing only authenticated HTTP requests.
* Furthermore, it lets users to configure where to retrieve the user info from
* and what to do in case unsuccessful authentication
*
* For example:
* {{{
* //in a Security trait
* def username(request: RequestHeader) = request.session.get("email")
* def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Application.login)
* def isAuthenticated(f: => String => Request[AnyContent] => Result) = {
* Authenticated(username, onUnauthorized) { user =>
* Action(request => f(user)(request))
* }
* }
* //then in a controller
* def index = isAuthenticated { username => implicit request =>
* Ok("Hello " + username)
* }
* }}}
*
* @tparam A the type of the user info value (e.g. `String` if user info consists only in a user name)
* @param userinfo function used to retrieve the user info from the request header
* @param onUnauthorized function used to generate alternative result if the user is not authenticated
* @param action the action to wrap
*/
def Authenticated[A](
userinfo: RequestHeader => Option[A],
onUnauthorized: RequestHeader => Result)(action: A => EssentialAction): EssentialAction = {
EssentialAction { request =>
userinfo(request).map { user =>
action(user)(request)
}.getOrElse {
Done(onUnauthorized(request), Input.Empty)
}
}
}
/**
* Key of the username attribute stored in session.
*/
lazy val username: String = Play.maybeApplication.flatMap(_.configuration.getString("session.username")) getOrElse ("username")
/**
* Wraps another action, allowing only authenticated HTTP requests.
*
* The user name is retrieved from the (configurable) session cookie, and added to the HTTP request’s
* `username` attribute. In case of failure it returns an Unauthorized response (401)
*
* For example:
* {{{
* //in a Security trait
* def isAuthenticated(f: => String => Request[AnyContent] => Result) = {
* Authenticated { user =>
* Action(request => f(user)(request))
* }
* }
* //then in a controller
* def index = isAuthenticated { username => implicit request =>
* Ok("Hello " + username)
* }
* }}}
*
* @param action the action to wrap
*/
def Authenticated(action: String => EssentialAction): EssentialAction = Authenticated(
req => req.session.get(username),
_ => Unauthorized(views.html.defaultpages.unauthorized()))(action)
/**
* An authenticated request
*
* @param user The user that made the request
*/
class AuthenticatedRequest[A, U](val user: U, request: Request[A]) extends WrappedRequest[A](request)
/**
* An authenticated action builder.
*
* This can be used to create an action builder, like so:
*
* {{{
* // in a Security trait
* object Authenticated extends AuthenticatedBuilder(req => getUserFromRequest(req))
*
* // then in a controller
* def index = Authenticated { implicit request =>
* Ok("Hello " + request.user)
* }
* }}}
*
* It can also be used from an action builder, for example:
*
* {{{
* class AuthenticatedDbRequest[A](val user: User,
* val conn: Connection,
* request: Request[A]) extends WrappedRequest[A](request)
*
* object Authenticated extends ActionBuilder[AuthenticatedDbRequest] {
* def invokeBlock[A](request: Request[A], block: (AuthenticatedDbRequest[A]) => Future[Result]) = {
* AuthenticatedBuilder(req => getUserFromRequest(req)).authenticate(request, { authRequest: AuthenticatedRequest[A, User] =>
* DB.withConnection { conn =>
* block(new AuthenticatedDbRequest[A](authRequest.user, conn, request))
* }
* })
* }
* }
* }}}
*
* @param userinfo The function that looks up the user info.
* @param onUnauthorized The function to get the result for when no authenticated user can be found.
*/
class AuthenticatedBuilder[U](userinfo: RequestHeader => Option[U],
onUnauthorized: RequestHeader => Result = _ => Unauthorized(views.html.defaultpages.unauthorized()))
extends ActionBuilder[({ type R[A] = AuthenticatedRequest[A, U] })#R] {
def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A, U]) => Future[Result]) =
authenticate(request, block)
/**
* Authenticate the given block.
*/
def authenticate[A](request: Request[A], block: (AuthenticatedRequest[A, U]) => Future[Result]) = {
userinfo(request).map { user =>
block(new AuthenticatedRequest(user, request))
} getOrElse {
Future.successful(onUnauthorized(request))
}
}
}
/**
* An authenticated action builder.
*
* This can be used to create an action builder, like so:
*
* {{{
* // in a Security trait
* object Authenticated extends AuthenticatedBuilder(req => getUserFromRequest(req))
*
* // then in a controller
* def index = Authenticated { implicit request =>
* Ok("Hello " + request.user)
* }
* }}}
*
* It can also be used from an action builder, for example:
*
* {{{
* class AuthenticatedDbRequest[A](val user: User,
* val conn: Connection,
* request: Request[A]) extends WrappedRequest[A](request)
*
* object Authenticated extends ActionBuilder[AuthenticatedDbRequest] {
* def invokeBlock[A](request: Request[A], block: (AuthenticatedDbRequest[A]) => Future[Result]) = {
* AuthenticatedBuilder(req => getUserFromRequest(req)).authenticate(request, { authRequest: AuthenticatedRequest[A, User] =>
* DB.withConnection { conn =>
* block(new AuthenticatedDbRequest[A](authRequest.user, conn, request))
* }
* })
* }
* }
* }}}
*/
object AuthenticatedBuilder {
/**
* Create an authenticated builder
*
* @param userinfo The function that looks up the user info.
* @param onUnauthorized The function to get the result for when no authenticated user can be found.
*/
def apply[U](userinfo: RequestHeader => Option[U],
onUnauthorized: RequestHeader => Result = _ => Unauthorized(views.html.defaultpages.unauthorized())): AuthenticatedBuilder[U] = new AuthenticatedBuilder(userinfo, onUnauthorized)
/**
* Simple authenticated action builder that looks up the username from the session
*/
def apply(): AuthenticatedBuilder[String] = apply[String](req => req.session.get(username))
}
}
Other Play Framework source code examplesHere is a short list of links related to this Play Framework Security.scala source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.