En la anterior entrega (http://deancos.com/articles/mini-tutorial-silex-anadiendo-dependencias-twig-ii/) vimos como podíamos integrar fácilmente el sistema de plantilla twig con Silex, gracias a lo cual ya podíamos maquetar nuestros resultados mas fácilmente.
Hoy vamos a dar un nuevo paso en nuestro pequeño programa y vamos a preparar nuestra aplicación para poder autenticar y autorizar.
Vamos a añadir una nueva dependencia al proyecto: Security. Como vimos en los anteriores capítulos lo único que necesitamos es añadir la dependencia a nuestro composer.json:
"symfony/security": "~2.3",
Una vez guardado el fichero tendremos algo como esto:
{
"require": {
"silex/silex": "~1.1",
"twig/twig": ">=1.8,<2.0-dev",
"symfony/twig-bridge": "~2.3",
"symfony/security": "~2.3"
}
}
Ahora podemos actualizar nuestro proyecto:
php composer.phar update
Bueno, ahora ya tenemos listas las dependencias que necesitamos para poder empezar a preparar nuestro entorno de seguridad.
Los primeros servicios que registramos son UrlGeneratorServiceProvider y _SessionServiceProvider_, ambos son servicios muy específicos que mas adelante utilizaremos, por ahora creo que sus nombre son bastante auto-explicativos.
Ya sabemos, en nuestro index.php registrar los servicios:
new Silex\Provider\UrlGeneratorServiceProvider());
$app->register(new Silex\Provider\SessionServiceProvider());
...
$app->register(
Bueno, ahora vamos a registrar el servicio principal, _SecurityServiceProvider_, y lo configuraremos por defecto para poder hacer nuestras primeras pruebas. Por ahora como no tenemos aun base de datos podemos utilizar una configuración como la siguiente.
$app->register(new Silex\Provider\SecurityServiceProvider(), array(
"security.firewalls" => array(
"admin" => array(
"pattern" => "^/admin/",
"form" => array("login_path" => "/login", "check_path" => "/admin/login_check"),
"logout" => array("logout_path" => "/admin/logout"),
"users" => array(
"admin" => array("ROLE_ADMIN", "5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=="),
),
),
)
));
No entrare mucho a explicar como funciona la configuración pues en siguientes capítulos cuando lo integremos con la base de datos podremos explicarlo mas a fondo. Por ahora con saber que hemos configurado las rutas por defecto para poder hacer login/logout y que hemos creado un usuario admin es suficiente.
Ahora vamos a crear en nuestro controlador frontal una acción para hacer _login_:
$app->get("/login", function(Request $request) use ($app) {
return $app["twig"]->render("login.html", array(
"error" => $app["security.last_error"]($request),
"last_username" => $app["session"]->get("_security.last_username"),
));
});
Y su vista correspondiente con el formulario de _login_:
<form action="{{ path("admin_login_check") }}" method="post">
{{ error }}
<input type="text" name="_username" value="{{ last_username }}" />
<input type="password" name="_password" value="" />
<input type="submit" />
</form>
En este punto os podréis preguntar que significa y de donde sale esta linea en la vista: path(“admin_login_check”), pues efectivamente de uno de los servicios que antes registramos, exactamente de _UrlGeneratorServiceProvider_, que justamente se dedica a generar las urls que necesitamos de manera dinámica.
Bueno ya tenemos nuestra acción de login y su vista correspondiente.
Vamos a cambiar un poco lo que teníamos de capítulos anteriores para que tenga mas sentido con esta nueva funcionalidad, este seria nuestro nuevo controlador frontal:
require_once __DIR__."/../vendor/autoload.php";
use Symfony\Component\HttpFoundation\Request;
$app = new Silex\Application();
$app["debug"] = true;
$app->register(new Silex\Provider\TwigServiceProvider(), array("twig.path" => __DIR__."/views",));
$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
$app->register(new Silex\Provider\SessionServiceProvider());
$app->register(new Silex\Provider\SecurityServiceProvider(), array(
"security.firewalls" => array(
"admin" => array(
"pattern" => "^/admin/",
"form" => array("login_path" => "/login", "check_path" => "/admin/login_check"),
"logout" => array("logout_path" => "/admin/logout"),
"users" => array(
"admin" => array("ROLE_ADMIN", "5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=="),
),
),
)
));
$app->get("/", function () use ($app) {
$user = $app["session"]->get("user");
return $app["twig"]->render("index.html", array("user" => $user));
});
$app->get("/login", function(Request $request) use ($app) {
return $app["twig"]->render("login.html", array(
"error" => $app["security.last_error"]($request),
"last_username" => $app["session"]->get("_security.last_username"),
));
});
$app->get("/admin", function () use ($app) {
return "Admin site";
});
$app->run();
Hemos añadido una nueva acción, _/admin_, para comprobar que funciona perfectamente el sistema de seguridad.
nota: la url /admin esta definida en la configuración de SecurityServiceProvider, es el valor de la clave pattern: “pattern” => “^/admin/“
También hemos cambiado un poco nuestra vista, index.html:
Hello {{ user }}, welcome!
<p>
<a href="login">Login</a>
<a href="{{ path("admin_logout") }}">Logout</a>
</p>
Una de las lineas nuevas del controlador frontal que aun no hemos explicado en la utilización de la clase request para recoger la petición:
Para utilizarlo lo único que tenemos que hacer es importarla y utilizarla en nuestra acción:
use Symfony\Component\HttpFoundation\Request;
$app->get("/login", function(Request $request) use ($app) {}
Ahora si entramos con nuestro navegador preferido a nuestra aplicación podremos probar y experimentar con el sistema de seguridad.
En próximas entregas entraremos mas a fondo en estos temas y otros también muy interesantes.