1 | Lets implement a simple Auth controller |
---|
2 | > **Note** The important part is storing the username in the session so the Security trait works. |
---|
3 | |
---|
4 | object Auth extends Controller { |
---|
5 | |
---|
6 | val loginForm = Form( |
---|
7 | tuple( |
---|
8 | "email" -> text, |
---|
9 | "password" -> text |
---|
10 | ) verifying ("Invalid email or password", result => result match { |
---|
11 | case (email, password) => check(email, password) |
---|
12 | }) |
---|
13 | ) |
---|
14 | |
---|
15 | def check(username: String, password: String) = { |
---|
16 | (username == "admin" && password == "1234") |
---|
17 | } |
---|
18 | |
---|
19 | def login = Action { implicit request => |
---|
20 | Ok(html.login(loginForm)) |
---|
21 | } |
---|
22 | |
---|
23 | def authenticate = Action { implicit request => |
---|
24 | loginForm.bindFromRequest.fold( |
---|
25 | formWithErrors => BadRequest(html.login(formWithErrors)), |
---|
26 | user => Redirect(routes.Application.index).withSession(Security.username -> user._1) |
---|
27 | ) |
---|
28 | } |
---|
29 | |
---|
30 | def logout = Action { |
---|
31 | Redirect(routes.Auth.login).withNewSession.flashing( |
---|
32 | "success" -> "You are now logged out." |
---|
33 | ) |
---|
34 | } |
---|
35 | } |
---|
36 | |
---|
37 | We submit the login form to `authentication` the validation kicks in and calls the `check` method and if that returns true we redirect to `routes.Application.index` setting the `username` session variable. |
---|
38 | |
---|
39 | Have a look at the [login view](https://github.com/playframework/Play20/blob/master/samples/scala/zentasks/app/views/login.scala.html) from zentasks to see how the form is implemented. |
---|
40 | |
---|
41 | > **What is Security.username:** This method checks if there is a config variable called `session.username` and if not, falls back to using `username` as the session variable name. |
---|
42 | |
---|
43 | ## Authorization |
---|
44 | We need to implement the [play.api.mvc.Security](https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/mvc/Security.scala) trait: |
---|
45 | |
---|
46 | trait Secured { |
---|
47 | |
---|
48 | def username(request: RequestHeader) = request.session.get(Security.username) |
---|
49 | |
---|
50 | def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Auth.login) |
---|
51 | |
---|
52 | def withAuth(f: => String => Request[AnyContent] => Result) = { |
---|
53 | Security.Authenticated(username, onUnauthorized) { user => |
---|
54 | Action(request => f(user)(request)) |
---|
55 | } |
---|
56 | } |
---|
57 | |
---|
58 | /** |
---|
59 | * This method shows how you could wrap the withAuth method to also fetch your user |
---|
60 | * You will need to implement UserDAO.findOneByUsername |
---|
61 | */ |
---|
62 | def withUser(f: User => Request[AnyContent] => Result) = withAuth { username => implicit request => |
---|
63 | UserDAO.findOneByUsername(username).map { user => |
---|
64 | f(user)(request) |
---|
65 | }.getOrElse(onUnauthorized(request)) |
---|
66 | } |
---|
67 | } |
---|
68 | |
---|
69 | > The Secured trait can live in the same file as the Auth controller |
---|
70 | |
---|
71 | And to use it: |
---|
72 | |
---|
73 | object Application extends Controller with Secured { |
---|
74 | |
---|
75 | def index = withAuth { username => implicit request => |
---|
76 | Ok(html.index(username)) |
---|
77 | } |
---|
78 | |
---|
79 | def user() = withUser { user => implicit request => |
---|
80 | val username = user.username |
---|
81 | Ok(html.user(user)) |
---|
82 | } |
---|
83 | } |
---|
84 | |
---|
85 | * For an example check out the [zentask sample](https://github.com/playframework/Play20/tree/master/samples/scala/zentasks) |
---|
86 | * There is also a more advanced security plugin called [Deadbolt](https://github.com/schaloner/deadbolt-2) |
---|