El módulo Secure es uno de los módulos que vienen por defecto con la distribución de Play. Permite añadir login mediante usuario y contraseña a nuestra aplicación.

Instalación

Añadimos las dependencias del módulo de seguridad

conf/dependencies.yml

1
2
3
4
5
# Application dependencies

require: - play - play -> secure

Ejecutamos en la terminal

play dependencies
play eclipsify
Estos dos comandos los debemos ejecutar cada vez que modifiquemos nuestro fichero de dependencias. El primer comando se descarga en el proyecto las dependencias necesarias y el segundo actualiza la configuración del proyecto de Eclipse, para que tenga en cuenta las dependencias nuevas. Actualiza el proyecto de Eclipse pulsando F5 con el proyecto seleccionado.

Añade las rutas por defecto conf/routes

*      /                module:secure

Importante Cada vez que añadas una nueva librerías deberás reiniciar el servidor

Uso

Anota el controlador al que quieras ponerle restricción de seguridad con la anotación @With(Secure.class)

1
2
3
4
5
6
7
package controllers;

@With(Secure.class) public class Timeline extends Controller { }

Ahora cuando accedes a http://localhost:9000/ nos redireccionará a la página de login http://localhost:9000/login

Personalizando la autenticación

Para personalizar el mecanismo de autenticación debemos crear una clase que extienda de Secure.Security y sobreescribir el método authenticate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package controllers;
import models.User;

public class Security extends Secure.Security { static boolean authenticate(String username, String password) { User user = User.find(“byUsername”, username).first(); return user != null && user.password.equals(password); }

<span class="kd">static</span> <span class="n">User</span> <span class="nf">userConnected</span><span class="o">(){</span>
    <span class="n">User</span> <span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="s">"byUsername"</span><span class="o">,</span> <span class="n">session</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"username"</span><span class="o">)).</span><span class="na">first</span><span class="o">();</span>
    <span class="k">return</span> <span class="n">user</span><span class="o">;</span>
<span class="o">}</span>   

}

Prueba a hacer login con algunos de los usuarios definido en initial-data.yml

Usuario conectado y logout

Vamos a modificar la plantilla para mostrar el usuario que está conectado y ponerle un botón que le permita desconectarse de la aplicación.

app/views/main.hml

1
2
3
<form action=“@{Secure.logout}” class=“pull-right”>
   <button class=“btn” type=“submit”>${controllers.Security.userConnected().username} - Salir</button>
</form>

Personalizando la página de login

Para personalizar la página de login lo único que tenemos que hacer es crear una nueva vista que esté en la misma ruta que la vista del módulo. Si nos fijamos en el proyecto de Eclipse tenemos un enlace al proyecto secure (aparece una carpeta de código con una flecha). En el proyecto tenemos la vista views.Secure.login.html que es la que muestra la pantalla de login. Lo que devemos hacer es crear una vista, dentro de nuestro proyecto, que esté en la misma ruta.

Basándonos en la vista original y aplicandole algunos estilos de twitter bootstrap tenemos esto

app/views/Secure/login.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!DOCTYPE html>
<html>
    <head>
        <title>Login</title>
        <meta charset=“utf-8”>
        <link rel=“shortcut icon” type=“image/png” href=“@{‘/public/images/favicon.png’}”>
        <script src=“@{‘/public/javascripts/jquery-1.5.2.min.js’}” type=“text/javascript” charset=“${_response_encoding}”></script>
        <link rel=“stylesheet” href=“http://twitter.github.com/bootstrap/1.3.0/bootstrap.min.css”>
        <link rel=“stylesheet” media=“screen” href=“@{‘/public/stylesheets/main.css’}”>
    </head>
    <body style=“padding: 0”>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container"</span> <span class="nt">&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"content"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"page-header"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;h1&gt;</span>Login<span class="nt">&lt;/h1&gt;</span>
        <span class="nt">&lt;/div&gt;</span>
        <span class="nt">&lt;div&gt;</span>
            #{form @authenticate()}

                #{if flash.error}
                    <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">"alert-message error"</span><span class="nt">&gt;</span>
                        <span class="err">&amp;</span>{flash.error}
                    <span class="nt">&lt;/p&gt;</span>
                #{/if}
                #{if flash.success}
                    <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">"alert-message success"</span><span class="nt">&gt;</span>
                        <span class="err">&amp;</span>{flash.success}
                    <span class="nt">&lt;/p&gt;</span>
                #{/if}


            <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"clearfix"</span><span class="nt">&gt;</span>
                <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">"username"</span><span class="nt">&gt;</span><span class="err">&amp;</span>{'secure.username'}<span class="nt">&lt;/label&gt;</span>
                <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"input"</span><span class="nt">&gt;</span>
                    <span class="nt">&lt;input</span> <span class="na">class=</span><span class="s">"xlarge"</span> <span class="na">id=</span><span class="s">"username"</span> <span class="na">name=</span><span class="s">"username"</span> <span class="na">size=</span><span class="s">"30"</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">value=</span><span class="s">"${flash.username}"</span> <span class="nt">/&gt;</span>
                <span class="nt">&lt;/div&gt;</span>
            <span class="nt">&lt;/div&gt;</span>

            <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"clearfix"</span><span class="nt">&gt;</span>
                <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">"password"</span><span class="nt">&gt;</span><span class="err">&amp;</span>{'secure.password'}<span class="nt">&lt;/label&gt;</span>
                <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"input"</span><span class="nt">&gt;</span>
                    <span class="nt">&lt;input</span> <span class="na">class=</span><span class="s">"xlarge"</span> <span class="na">id=</span><span class="s">"password"</span> <span class="na">name=</span><span class="s">"password"</span> <span class="na">size=</span><span class="s">"30"</span> <span class="na">type=</span><span class="s">"password"</span> <span class="na">value=</span><span class="s">""</span> <span class="nt">/&gt;</span>
                <span class="nt">&lt;/div&gt;</span>
            <span class="nt">&lt;/div&gt;</span>
            <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"input"</span><span class="nt">&gt;</span>
                <span class="nt">&lt;ul</span> <span class="na">class=</span><span class="s">"inputs-list"</span><span class="nt">&gt;</span>
                    <span class="nt">&lt;li&gt;&lt;label&gt;</span>
                        <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"checkbox"</span> <span class="na">name=</span><span class="s">"optionsCheckboxes"</span> <span class="na">value=</span><span class="s">"true"</span> <span class="err">${</span><span class="na">flash</span><span class="err">.</span><span class="na">remember</span> <span class="err">?</span> <span class="err">'</span><span class="na">checked=</span><span class="s">"true"</span><span class="err">'</span> <span class="na">:</span> <span class="err">''}</span><span class="nt">&gt;</span>
                        <span class="nt">&lt;span&gt;</span><span class="err">&amp;</span>{'secure.remember'}<span class="nt">&lt;/span&gt;</span>
                    <span class="nt">&lt;/label&gt;&lt;/li&gt;</span>
                <span class="nt">&lt;/ul&gt;</span>
            <span class="nt">&lt;/div&gt;</span>

            <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"input"</span><span class="nt">&gt;</span>
                <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"submit"</span> <span class="na">class=</span><span class="s">"btn primary"</span> <span class="na">value=</span><span class="s">"&amp;{'secure.signin'}"</span><span class="nt">&gt;</span>
            <span class="nt">&lt;/div&gt;</span>    
            #{/form}
        <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>

    <span class="nt">&lt;footer&gt;</span>
        <span class="nt">&lt;p&gt;</span>
            <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"http://axelhzf.github.com/play-curso/"</span><span class="nt">&gt;</span>Tutorial<span class="nt">&lt;/a&gt;</span> - <span class="nt">&lt;a</span>
                <span class="na">href=</span><span class="s">"https://github.com/axelhzf/play-curso"</span><span class="nt">&gt;</span>Código fuente<span class="nt">&lt;/a&gt;</span>
        <span class="nt">&lt;/p&gt;</span>
    <span class="nt">&lt;/footer&gt;</span>

<span class="nt">&lt;/div&gt;</span>
<span class="c">&lt;!-- /container --&gt;</span>

</body> </html>

Página de login

Ejercicios: Añadir comprobación adicional

Vamos a establecer algunos usuarios administrador, que tendrán más privilegios que otros. Por ejemplo, los usuarios administradores serán los únicos capaces de ver la página de las estadísticas.

Consejos:

Solución

Modifica la entidad User

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package models;

import java.util.ArrayList; import java.util.List; import javax.persistence.Entity; import javax.persistence.ManyToMany; import play.db.jpa.Model;

@Entity public class User extends Model {

<span class="kd">public</span> <span class="n">String</span> <span class="n">username</span><span class="o">;</span>

<span class="kd">public</span> <span class="n">String</span> <span class="n">password</span><span class="o">;</span>

<span class="kd">public</span> <span class="kt">boolean</span> <span class="n">admin</span><span class="o">;</span>

<span class="nd">@ManyToMany</span>
<span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">User</span><span class="o">&gt;</span> <span class="n">follows</span><span class="o">;</span>

<span class="kd">public</span> <span class="nf">User</span><span class="o">(</span><span class="n">String</span> <span class="n">username</span><span class="o">,</span> <span class="n">String</span> <span class="n">password</span><span class="o">)</span> <span class="o">{</span>
    <span class="kd">super</span><span class="o">();</span>
    <span class="k">this</span><span class="o">.</span><span class="na">username</span> <span class="o">=</span> <span class="n">username</span><span class="o">;</span>
    <span class="k">this</span><span class="o">.</span><span class="na">password</span> <span class="o">=</span> <span class="n">password</span><span class="o">;</span>
    <span class="k">this</span><span class="o">.</span><span class="na">admin</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
    <span class="n">follows</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">User</span><span class="o">&gt;();</span>
<span class="o">}</span>

}

Añade la anotación @Check en el método que renderiza la página de las estadísticas

1
2
@Check(“isAdmin”)
public static void stats(){

Implementa la comprobación “isAdmin”

1
2
3
4
5
6
7
8
static boolean check(String profile) {
    User user = userConnected();
    if (“isAdmin”.equals(profile)) {
        return user.admin;
    } else {
        return false;
    }
}

Modifica la plantilla para ocultar el enlace a la página de estadísticas si el usuario no es administrador.

1
2
3
  #{secure.check ‘isAdmin’}
        <li><a href=“@{Timeline.stats}”>Estadísticas</a></li>
    #{/secure.check}