SlideShare une entreprise Scribd logo
1  sur  64
Télécharger pour lire hors ligne
Seguridad
Realizada por:
Christian Aquino |@cj_aquino
Diego Ramirez |@thedarsideofit
Gonzalo Alonso |@GonzaloAlonsoD
Diego Barros |@Inmzombie
Para: Hydras C&S |@hydras_cs
Basada en Libro Symfony 2 en español Nacho Pacheco y The Book
Seguridad etapas
Autenticación HTTP
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
http_basic:
realm: "Secured Demo Area"
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
Autenticación HTTP
providers:
in_memory:
memory:
users:
ryan: { password: ryanpass, roles:
'ROLE_USER' }
admin: { password: kitten, roles:
'ROLE_ADMIN' }
encoders:
SymfonyComponentSecurityCoreUserUser:
plaintext
Autenticación HTTP
● Hay dos usuarios en el sistema (ryan y admin);
● Los usuarios se autentican a través de la autenticación
HTTP básica del sistema;
● Cualquier URL que coincida con /admin/* está
protegida, y sólo el usuario admin puede acceder a
ellas;
● Todas las URL que no coincidan con /admin/* son
accesibles para todos los usuarios (y nunca se pide al
usuario que se registre).
Cortafuegos (Autenticación)
Cortafuegos (Autenticación)
El trabajo del cortafuegos es determinar si el usuario necesita
estar autenticado, y si lo hace, enviar una respuesta al usuario
para iniciar el proceso de autenticación.
En este ejemplo el patrón (^/) concordará con cada petición
entrante.
Cualquier usuario puede acceder a /foo sin que se le pida se
autentique.
Puesto que no hay rol especial necesario para acceder a /foo
(bajo la sección access_control), la petición se puede llevar a
cabo sin solicitar al usuario se autentique
Si eliminas la clave anonymous, el cortafuegos siempre hará
que un usuario se autentique inmediatamente.
Control de acceso (Autorización)
Control de acceso (Autorización)
Si un usuario solicita /admin/foo, la configuración
access_control dice que cualquier URL coincidente con el
patrón de la expresión regular ^/admin (/admin o /admin/*)
requiere el rol ROLE_ADMIN.
Los roles son la base para la mayor parte de la
autorización: solo puede acceder a /admin/foo si cuenta
con el rol ROLE_ADMIN.
Control de acceso (Autorización)
Control de acceso (Autorización)
El usuario ryan se autentica correctamente con el
cortafuegos. Pero como ryan no cuenta con el rol
ROLE_ADMIN, se le sigue negando el acceso a
/admin/foo. En última instancia, el usuario debe ver algún
tipo de mensaje indicándole que se le ha denegado el
acceso.
Cuando Symfony niega el acceso al usuario, él verá una
pantalla de error y recibe un código de estado HTTP 403
(Prohibido).
Control de acceso (Autorización)
Control de acceso (Autorización)
Si admin solicita /admin/foo, después de haberse
autenticado, la capa de control de acceso le permitirá
pasar a través de la petición.
El flujo de la petición cuando un usuario solicita un recurso
protegido es sencillo. Independientemente del método de
autenticación, siempre es el mismo:
1. Un usuario accede a un recurso protegido
2. Se redirige al usuario al formulario de acceso
3. El usuario presenta sus credenciales
(usuario/contraseña)
4. El cortafuegos autentica al usuario
5. El nuevo usuario autenticado intenta de nuevo la
petición original.
Usando un formulario de acceso
tradicional
activa el formulario de acceso en el cortafuegos:
# app/config/security.yml
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: login
check_path: login_check
Usando un formulario de acceso
tradicional
Si no necesitas personalizar tus valores login_path o
check_path (los valores utilizados aquí son los
valores predeterminados), puedes acortar tu
configuración:
form_login: ~
Configurar rutas
# app/config/routing.yml
login:
pattern: /login
defaults: { _controller: AcmeSecurityBundle:
Security:login }
login_check:
pattern: /login_check
Controlador
// src/Acme/SecurityBundle/Controller/SecurityController.php;
namespace AcmeSecurityBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentSecurityCoreSecurityContext;
class SecurityController extends Controller
{
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
Controlador
// obtiene el error de inicio de sesión si lo hay
if ($request->attributes->has(
SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
SecurityContext::AUTHENTICATION_ERROR
);
} else {
$error = $session->get(
SecurityContext::AUTHENTICATION_ERROR);
$session->remove(
SecurityContext::AUTHENTICATION_ERROR);
Controlador
}
return $this->render(
'AcmeSecurityBundle:Security:login.html.twig',
array(
// último nombre de usuario ingresado
'last_username' => $session->get(
SecurityContext::LAST_USERNAME),
'error' => $error,
)
);
}
}
Controlador
El trabajo es mostrar el formulario al usuario y los errores
de ingreso que puedan haber ocurrido, el propio sistema de
seguridad se encarga de verificar el nombre de usuario y
contraseña y la autenticación del usuario.
Plantilla
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
<form action="{{ path('login_check') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username"
value="{{ last_username }}" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password"
/>
<button type="submit">login</button>
</form>
Plantilla
Requisitos:
Presentando el formulario a /login_check (a ​​través de la ruta
login_check), el sistema de seguridad debe interceptar el envío
del formulario y procesarlo automáticamente.
El sistema de seguridad espera que los campos presentados se
llamen _username y _password.
Proceso:
1. Intenta acceder
2. El cortafuegos inicia la autenticación (/login)
3. /login reproduce el formulario
4. El usuario envía el formulario de acceso a /login_check
5. El sistema de seguridad intercepta la petición, comprueba
las credenciales, autentica al usuario si todo está correcto, y
si no, envía al usuario de nuevo al formulario de acceso.
Evitando errores comunes
1. Crea las rutas correctas
2. Asegúrate de que la página de inicio de sesión no
esté protegida
3. Asegúrate de que /login_check está detrás de un
cortafuegos
4. Múltiples cortafuegos no comparten el contexto de
seguridad
Autorizando
Una vez que el usuario se ha autenticado, comienza la
autorización. La autorización proporciona una forma
estándar y potente para decidir si un usuario puede
acceder a algún recurso (una URL, un modelo de objetos,
una llamada a un método, ...). Esto funciona asignando
roles específicos a cada usuario y, a continuación,
requiriendo diferentes roles para diferentes recursos.
Protegiendo patrones de URL
# app/config/security.yml
security:
# ...
access_control:
- { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }
- { path: ^/admin, roles: ROLE_ADMIN }
^/admin/users
/admin/users
/users/admin
Entendiendo como trabaja
access_control
Cada access_control tiene varias opciones que configuran
dos diferentes cosas: (a) la petición entrante emparejada
debe tener esta entrada de control de acceso y (b) una vez
emparejada, debe tener algún tipo de restricción de acceso
aplicable:
# app/config/security.yml
security:
# ...
access_control:
- { path: ^/admin/users, roles: ROLE_SUPER_ADMIN }
- { path: ^/admin, roles: ROLE_ADMIN }
Emparejando opciones
Symfony2 crea una instancia de
SymfonyComponentHttpFoundationRequestMatcher para
cada entrada access_control.
Las siguientes opciones de access_control se utilizan para
emparejar:
● path
● ip
● host
● methods
Emparejando opciones
# app/config/security.yml
security:
# ...
access_control:
- { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1
}
- { path: ^/admin, roles: ROLE_USER_HOST, host:
symfony.com }
- { path: ^/admin, roles: ROLE_USER_METHOD,
methods: [POST, PUT] }
- { path: ^/admin, roles: ROLE_USER }
1. { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 }
2. { path: ^/admin, roles: ROLE_USER_HOST, host: symfony.com }
3. { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] }
4. { path: ^/admin, roles: ROLE_USER }
1. { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 }
2. { path: ^/admin, roles: ROLE_USER_HOST, host: symfony.com }
3. { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] }
4. { path: ^/admin, roles: ROLE_USER }
1. { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 }
2. { path: ^/admin, roles: ROLE_USER_HOST, host: symfony.com }
3. { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] }
4. { path: ^/admin, roles: ROLE_USER }
Forzando el acceso
Al decidir que entrada access_control concuerda (si la hay),
aplica las restricciones de acceso basándose en las opciones
roles y requires_channel:
● role Si el usuario no tiene determinado rol o roles, entonces
el acceso es denegado (internamente, se lanza una
SymfonyComponentSecurityCoreExceptionAccessDenied
Exception);
● requires_channel Si el canal de la petición entrante (p. ej.
http) no concuerda con este valor (p. ej. https), el usuario
será redirigido (p. ej. redirigido de http a https, o viceversa).
Si el acceso es denegado, el sistema intentará autenticar al
usuario si aún no lo está. Si el usuario ya inició sesión, se
mostrará la página del error 403 «acceso denegado».
Protegiendo por IP
# app/config/security.yml
security:
# ...
access_control:
- { path: ^/esi, roles:
IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
- { path: ^/esi, roles: ROLE_NO_ACCESS }
Protegiendo por canal
# app/config/security.yml
security:
# ...
access_control:
- {
path: ^/cart/checkout,
roles: IS_AUTHENTICATED_ANONYMOUSLY,
requires_channel: https
}
Protegiendo un controlador
// ...
use SymfonyComponentSecurityCoreExceptionAccessDeniedException;
public function helloAction($name)
{
if (false === $this->get('security.context')
->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
// ...
}
Protegiendo un controlador usando
anotaciones
// ...
use JMSSecurityExtraBundleAnnotationSecure;
/**
* @Secure(roles="ROLE_ADMIN")
*/
public function helloAction($name)
{
// ...
}
Usuarios
De donde provienen los usuarios? (Proveedores de usuarios)
El usuario envía un conjunto de credenciales (username y
password). El trabajo del sistema de autenticación es
concordar esas credenciales contra una piscina de
usuarios.
Los usuarios pueden venir de cualquier parte. Todo lo que
proporcione usuarios a la autenticación se llama
«proveedor de usuario».
Proveedores de usuario más comunes:
Carga usuarios de un archivo de configuración.
Carga usuarios de una tabla de la base de datos.
Especificando usuarios en un
archivo de configuración (en memoria)
# app/config/security.yml
security:
# ...
providers:
default_provider:
memory:
users:
ryan: {
password: ryanpass, roles: 'ROLE_USER' }
admin: {
password: kitten, roles: 'ROLE_ADMIN' }
Especificando usuarios en un
archivo de configuración (en memoria)
prudencia nombre de usuario utilizar la sintaxis alterna
users:
- { name: 77, password: pass, roles: 'ROLE_USER' }
- { name: user-name, password: pass, roles:
'ROLE_USER' }
Cargando usuarios de la base de
datos
Si deseas cargar tus usuarios a través del ORM de
Doctrine, lo puedes hacer creando una clase User y
configurando el proveedor entity.
Restringiendo el acceso
# app/config/security.yml
security:
firewalls:
frontend:
pattern: ^/*
anonymous: ~
form_login: ~
access_control:
- { path: ^/usuario/login, roles:
IS_AUTHENTICATED_ANONYMOUSLY }
Restringiendo el acceso
- { path: ^/usuario/registro, roles:
IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/usuario/*, roles: ROLE_USUARIO }
providers:
usuarios:
entity: {
class: ClaseUsuarioBundleEntityUsuario,
property: email }
encoders:
ClaseUsuarioBundleEntityUsuario: {
algorithm: sha512, iterations: 10 }
Creando la entidad usuario
$ php app/console doctrine:generate:entity
The Entity shortcut name: UsuarioBundle:Usuario
Configuration format (yml, xml, php, or annotation) [annotation]:
New field name (): nombre
Field type [string]: <Enter>
New field name (): apellidos
Field type [string]: <Enter>
New field name (): email
Field type [string]: <Enter>
New field name (): password
Field type [string]: <Enter>
New field name (): salt
Field type [string]: <Enter>
New field name (): <Enter>
Do you want to generate an empty repository class [no]? no
Do you confirm generation [yes]? yes
Creando el proveedor de usuarios
// src/Clase/UsuarioBundle/Entity/Usuario.php
namespace ClaseUsuarioBundleEntity;
use SymfonyComponentSecurityCoreUserUserInterface;
use DoctrineORMMapping as ORM;
/**
* CuponUsuarioBundleEntityUsuario
*
* @ORMEntity
*/
class Usuario implements UserInterface
{
...
}
// src/Clase/UsuarioBundle/Entity/Usuario.php
class Usuario implements UserInterface
{
function eraseCredentials() {}
function getRoles()
{
return array('ROLE_USUARIO');
}
function getUsername()
{
return $this->getEmail();
}
// ...
}
Implementar UserInterface
• eraseCredentials(), se invoca cuando la aplicación
necesita borrar la información más sensible del usuario,
como por ejemplo su contraseña.
• getPassword(), se invoca cada vez que la aplicación
necesita obtener la contraseña del usuario.
• getRoles(), cuando se autentica a un usuario, se invoca
este método para obtener un array con todos los roles que
posee.
• getSalt(), devuelve el valor que se utilizó para aleatorizar
la contraseña cuando se creó el usuario.
• getUsername(), se invoca para obtener el login o nombre
de usuario que se utiliza para autenticar a los usuarios.
Añadiendo el formulario de login
usuario_login:
pattern: /usuario/login
defaults: { _controller: UsuarioBundle:Default:login }
usuario_login_check:
pattern: /usuario/login_check
usuario_logout:
pattern: /usuario/logout
Añadiendo el formulario de login
• /login, se utiliza para mostrar el formulario de login.
• /login_check, es la acción que comprueba que el usuario
y contraseña introducidos son correctos.
• /logout, se emplea para desconectar al usuario logueado.
Actualizar ruta form_login
# app/config/security.yml
security:
firewalls:
frontend:
pattern: ^/*
anonymous: ~
form_login:
login_path: /usuario/login
check_path: /usuario/login_check
login_path: usuario_login
check_path: usuario_login_check
El controlador
//src/Clase/UsuarioBundle/Controller/DefaultController.php
namespace ClaseUsuarioBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentSecurityCoreSecurityContext;
class DefaultController extends Controller
{
public function loginAction()
{
$peticion = $this->getRequest();
$sesion = $peticion->getSession();
$error = $peticion->attributes->get(
El controlador
SecurityContext::AUTHENTICATION_ERROR,
$sesion->get(SecurityContext::AUTHENTICATION_
ERROR)
);
return $this->render('UsuarioBundle:Default:login.html.
twig', array(
'last_username' =>
$sesion->get(SecurityContext::LAST_USERNAME),
'error' => $error
));
}}
La vista del formulario
{# src/Clase/UsuarioBundle/Resources/views/Default/login.html.twig #}
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
<form action="{{ path('usuario_login_check') }}" method="post">
<label for="username">Usuario:</label>
<input type="text" id="username" name="_username"
value="{{ last_username }}" />
<label for="password">Contraseña:</label>
<input type="password" id="password" name="_password" />
<input type="submit" name="login" value="Acceder" />
</form>
Formulario de registro
#routing.yml
usuario_registro:
pattern: /registro
defaults: { _controller: UsuarioBundle:Default:registro }
Controlador registro
// src/Clase/UsuarioBundle/Controller/DefaultController.php
namespace ClaseUsuarioBundleController;
use SymfonyBundleFrameworkBundleControllerController;
use ClaseUsuarioBundleEntityUsuario;
use ClaseUsuarioBundleFormFrontendUsuarioType;
class DefaultController extends Controller
{
// ...
Controlador registro
public function registroAction()
{
$usuario = new Usuario();
$formulario = $this->createForm(new UsuarioType(),
$usuario);
return $this->render(
'UsuarioBundle:Default:registro.html.twig',
array('formulario' => $formulario->createView())
);
}
}
Plantilla registro
{# src/Clase/UsuarioBundle/Resources/views/Default/registro.html.twig #}
<form action="{{ path('usuario_registro') }}" method="post"
{{ form_enctype(formulario) }}>
{{ form_widget(formulario) }}
<input class="boton" type="submit"
value="Registrarme" />
</form>
Formulario registro
// src/Clase/UsuarioBundle/Form/Frontend/UsuarioType.php
namespace ClaseUsuarioBundleFormFrontend;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
class UsuarioType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder,
array $options)
{
$builder
->add('nombre')
->add('apellidos')
->add('email', 'email')
->add('password', 'repeated', array(
'type' => 'password',
'invalid_message' => 'Las dos contraseñas
deben coincidir',
'options' => array('label' => 'Contraseña')
))
;
}
public function setDefaultOptions
(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' =>
'ClaseUsuarioBundleEntityUsuario'
));
}
public function getName()
{
return 'clase_usuariobundle_usuariotype';
}
}
Controlador registro procesar form
public function registroAction()
{
$peticion = $this->getRequest();
$usuario = new Usuario();
$formulario = $this->createForm(new UsuarioType(),
$usuario);
if ($peticion->getMethod() == 'POST') {
$formulario->bind($peticion);
if ($formulario->isValid()) {
$encoder = $this->get('security.encoder_factory')
->getEncoder($usuario);
$usuario->setSalt(md5(time()));
$passwordCodificado =
$encoder->encodePassword(
$usuario->getPassword(),
$usuario->getSalt()
);
$usuario->setPassword($passwordCodificado);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($usuario);
$em->flush();
$token = new UsernamePasswordToken(
$usuario,
$usuario->getPassword(),
'usuarios',
$usuario->getRoles()
);
$this->container
->get('security.context')->setToken($token);
return $this->redirect($this->generateUrl('url'));
}
}
return $this->render(
'UsuarioBundle:Default:registro.html.twig',
array('formulario' => $formulario->createView())
);
}
}

Contenu connexe

Tendances

Jsp directiva page
Jsp directiva pageJsp directiva page
Jsp directiva page
jubacalo
 
Presentacion diseño web con jquery
Presentacion diseño web con jqueryPresentacion diseño web con jquery
Presentacion diseño web con jquery
Eutobar
 
Servlets y jsp
Servlets y jspServlets y jsp
Servlets y jsp
dtbadboy0
 
Programacion web java
Programacion web javaProgramacion web java
Programacion web java
César Ocampo
 
Framework .NET 3.5 13 Programación orientada a la red
Framework .NET 3.5 13 Programación orientada a la redFramework .NET 3.5 13 Programación orientada a la red
Framework .NET 3.5 13 Programación orientada a la red
Antonio Palomares Sender
 
DocumentacióN Del Sitio Web En Xml
DocumentacióN Del Sitio Web En XmlDocumentacióN Del Sitio Web En Xml
DocumentacióN Del Sitio Web En Xml
Antonio
 

Tendances (20)

Tema3
Tema3Tema3
Tema3
 
La magia de jquery
La magia de jqueryLa magia de jquery
La magia de jquery
 
Trabajo de base de datos en sqlserver
Trabajo de base de datos en sqlserverTrabajo de base de datos en sqlserver
Trabajo de base de datos en sqlserver
 
Acceso a BBDD mediante un servlet
Acceso a BBDD mediante un servletAcceso a BBDD mediante un servlet
Acceso a BBDD mediante un servlet
 
(Muy breve) Introduccion a jQuery
(Muy breve) Introduccion a jQuery(Muy breve) Introduccion a jQuery
(Muy breve) Introduccion a jQuery
 
Clase 2 conceptos fundamentales
Clase 2   conceptos fundamentalesClase 2   conceptos fundamentales
Clase 2 conceptos fundamentales
 
Jsp directiva page
Jsp directiva pageJsp directiva page
Jsp directiva page
 
Presentacion diseño web con jquery
Presentacion diseño web con jqueryPresentacion diseño web con jquery
Presentacion diseño web con jquery
 
Servicios web
Servicios webServicios web
Servicios web
 
Servlet Hola Mundo con Eclipse y Tomcat
Servlet Hola Mundo con Eclipse y TomcatServlet Hola Mundo con Eclipse y Tomcat
Servlet Hola Mundo con Eclipse y Tomcat
 
Find File Servlet DB
Find File Servlet DBFind File Servlet DB
Find File Servlet DB
 
Servlets y jsp
Servlets y jspServlets y jsp
Servlets y jsp
 
02 formulario iniciar sesion programar
02 formulario iniciar sesion   programar02 formulario iniciar sesion   programar
02 formulario iniciar sesion programar
 
Elementos de script en JSP
Elementos de script en JSPElementos de script en JSP
Elementos de script en JSP
 
Jsp servlet- Tutorial BD Conexión
Jsp servlet- Tutorial BD ConexiónJsp servlet- Tutorial BD Conexión
Jsp servlet- Tutorial BD Conexión
 
Programacion web java
Programacion web javaProgramacion web java
Programacion web java
 
Framework .NET 3.5 13 Programación orientada a la red
Framework .NET 3.5 13 Programación orientada a la redFramework .NET 3.5 13 Programación orientada a la red
Framework .NET 3.5 13 Programación orientada a la red
 
DocumentacióN Del Sitio Web En Xml
DocumentacióN Del Sitio Web En XmlDocumentacióN Del Sitio Web En Xml
DocumentacióN Del Sitio Web En Xml
 
Introduccion silverlight
Introduccion silverlightIntroduccion silverlight
Introduccion silverlight
 
Ajax
AjaxAjax
Ajax
 

Similaire à Clase 13 seguridad

Curso Avanzado Seguridad Acceso
Curso Avanzado Seguridad AccesoCurso Avanzado Seguridad Acceso
Curso Avanzado Seguridad Acceso
Antonio Durán
 

Similaire à Clase 13 seguridad (20)

Backend (sf2Vigo)
Backend (sf2Vigo)Backend (sf2Vigo)
Backend (sf2Vigo)
 
Symfony2 - ACL
Symfony2 - ACLSymfony2 - ACL
Symfony2 - ACL
 
Clase 5 controller
Clase 5 controllerClase 5 controller
Clase 5 controller
 
Tema 7
Tema 7Tema 7
Tema 7
 
Apache: Servidores web con autentificación
Apache: Servidores web con autentificaciónApache: Servidores web con autentificación
Apache: Servidores web con autentificación
 
Asegurando tus APIs Explorando el OWASP Top 10 de Seguridad en APIs.pdf
Asegurando tus APIs Explorando el OWASP Top 10 de Seguridad en APIs.pdfAsegurando tus APIs Explorando el OWASP Top 10 de Seguridad en APIs.pdf
Asegurando tus APIs Explorando el OWASP Top 10 de Seguridad en APIs.pdf
 
deSymfony 2011 - Tutorial #4: Formularios y seguridad
deSymfony 2011 - Tutorial #4: Formularios y seguridaddeSymfony 2011 - Tutorial #4: Formularios y seguridad
deSymfony 2011 - Tutorial #4: Formularios y seguridad
 
APIREST LARAVEL Y PHP.pptx
APIREST LARAVEL Y PHP.pptxAPIREST LARAVEL Y PHP.pptx
APIREST LARAVEL Y PHP.pptx
 
Gestión de usuarios en GNU/Linux. Módulos de autenticación PAM
Gestión de usuarios en GNU/Linux. Módulos de autenticación PAMGestión de usuarios en GNU/Linux. Módulos de autenticación PAM
Gestión de usuarios en GNU/Linux. Módulos de autenticación PAM
 
Desarrollo de sistios web
Desarrollo de sistios webDesarrollo de sistios web
Desarrollo de sistios web
 
Qué es eso de OAuth y como se implementa en Symfony2 (y otros)
Qué es eso de OAuth y como se implementa en Symfony2 (y otros)Qué es eso de OAuth y como se implementa en Symfony2 (y otros)
Qué es eso de OAuth y como se implementa en Symfony2 (y otros)
 
Construyendo APIs Seguras y Escalables
Construyendo APIs Seguras y Escalables Construyendo APIs Seguras y Escalables
Construyendo APIs Seguras y Escalables
 
Taller introduccion symfony2
Taller introduccion symfony2Taller introduccion symfony2
Taller introduccion symfony2
 
Endpoints Seguros en nuestra Rest-API
Endpoints Seguros en nuestra Rest-APIEndpoints Seguros en nuestra Rest-API
Endpoints Seguros en nuestra Rest-API
 
Curso Avanzado Seguridad Acceso
Curso Avanzado Seguridad AccesoCurso Avanzado Seguridad Acceso
Curso Avanzado Seguridad Acceso
 
PHP Tema 7 - Seguridad
PHP Tema 7 - SeguridadPHP Tema 7 - Seguridad
PHP Tema 7 - Seguridad
 
RESUMEN PROXY
RESUMEN PROXYRESUMEN PROXY
RESUMEN PROXY
 
servidor proxy
servidor proxyservidor proxy
servidor proxy
 
Resumen Servidor Proxy
Resumen Servidor ProxyResumen Servidor Proxy
Resumen Servidor Proxy
 
Vulnerabilidades en aplicaciones web
Vulnerabilidades en aplicaciones webVulnerabilidades en aplicaciones web
Vulnerabilidades en aplicaciones web
 

Plus de hydras_cs (8)

Clase 15 FOS
Clase 15 FOSClase 15 FOS
Clase 15 FOS
 
Clase 11 continuamos con formularios
Clase 11   continuamos con formulariosClase 11   continuamos con formularios
Clase 11 continuamos con formularios
 
Clase 7 el modelo
Clase 7  el modeloClase 7  el modelo
Clase 7 el modelo
 
Clase 6 twig
Clase 6 twigClase 6 twig
Clase 6 twig
 
Clase 4 routing
Clase 4 routingClase 4 routing
Clase 4 routing
 
Clase 3 instalación y primeros pasos
Clase 3 instalación y primeros pasosClase 3 instalación y primeros pasos
Clase 3 instalación y primeros pasos
 
Sensio labsdesktop
Sensio labsdesktopSensio labsdesktop
Sensio labsdesktop
 
Clase 1 introducción a symfony 2
Clase 1   introducción a symfony 2Clase 1   introducción a symfony 2
Clase 1 introducción a symfony 2
 

Clase 13 seguridad

  • 1. Seguridad Realizada por: Christian Aquino |@cj_aquino Diego Ramirez |@thedarsideofit Gonzalo Alonso |@GonzaloAlonsoD Diego Barros |@Inmzombie Para: Hydras C&S |@hydras_cs Basada en Libro Symfony 2 en español Nacho Pacheco y The Book
  • 3. Autenticación HTTP security: firewalls: secured_area: pattern: ^/ anonymous: ~ http_basic: realm: "Secured Demo Area" access_control: - { path: ^/admin, roles: ROLE_ADMIN }
  • 4. Autenticación HTTP providers: in_memory: memory: users: ryan: { password: ryanpass, roles: 'ROLE_USER' } admin: { password: kitten, roles: 'ROLE_ADMIN' } encoders: SymfonyComponentSecurityCoreUserUser: plaintext
  • 5. Autenticación HTTP ● Hay dos usuarios en el sistema (ryan y admin); ● Los usuarios se autentican a través de la autenticación HTTP básica del sistema; ● Cualquier URL que coincida con /admin/* está protegida, y sólo el usuario admin puede acceder a ellas; ● Todas las URL que no coincidan con /admin/* son accesibles para todos los usuarios (y nunca se pide al usuario que se registre).
  • 7. Cortafuegos (Autenticación) El trabajo del cortafuegos es determinar si el usuario necesita estar autenticado, y si lo hace, enviar una respuesta al usuario para iniciar el proceso de autenticación. En este ejemplo el patrón (^/) concordará con cada petición entrante. Cualquier usuario puede acceder a /foo sin que se le pida se autentique. Puesto que no hay rol especial necesario para acceder a /foo (bajo la sección access_control), la petición se puede llevar a cabo sin solicitar al usuario se autentique Si eliminas la clave anonymous, el cortafuegos siempre hará que un usuario se autentique inmediatamente.
  • 8. Control de acceso (Autorización)
  • 9. Control de acceso (Autorización) Si un usuario solicita /admin/foo, la configuración access_control dice que cualquier URL coincidente con el patrón de la expresión regular ^/admin (/admin o /admin/*) requiere el rol ROLE_ADMIN. Los roles son la base para la mayor parte de la autorización: solo puede acceder a /admin/foo si cuenta con el rol ROLE_ADMIN.
  • 10. Control de acceso (Autorización)
  • 11. Control de acceso (Autorización) El usuario ryan se autentica correctamente con el cortafuegos. Pero como ryan no cuenta con el rol ROLE_ADMIN, se le sigue negando el acceso a /admin/foo. En última instancia, el usuario debe ver algún tipo de mensaje indicándole que se le ha denegado el acceso. Cuando Symfony niega el acceso al usuario, él verá una pantalla de error y recibe un código de estado HTTP 403 (Prohibido).
  • 12. Control de acceso (Autorización)
  • 13. Control de acceso (Autorización) Si admin solicita /admin/foo, después de haberse autenticado, la capa de control de acceso le permitirá pasar a través de la petición. El flujo de la petición cuando un usuario solicita un recurso protegido es sencillo. Independientemente del método de autenticación, siempre es el mismo: 1. Un usuario accede a un recurso protegido 2. Se redirige al usuario al formulario de acceso 3. El usuario presenta sus credenciales (usuario/contraseña) 4. El cortafuegos autentica al usuario 5. El nuevo usuario autenticado intenta de nuevo la petición original.
  • 14. Usando un formulario de acceso tradicional activa el formulario de acceso en el cortafuegos: # app/config/security.yml security: firewalls: secured_area: pattern: ^/ anonymous: ~ form_login: login_path: login check_path: login_check
  • 15. Usando un formulario de acceso tradicional Si no necesitas personalizar tus valores login_path o check_path (los valores utilizados aquí son los valores predeterminados), puedes acortar tu configuración: form_login: ~
  • 16. Configurar rutas # app/config/routing.yml login: pattern: /login defaults: { _controller: AcmeSecurityBundle: Security:login } login_check: pattern: /login_check
  • 17. Controlador // src/Acme/SecurityBundle/Controller/SecurityController.php; namespace AcmeSecurityBundleController; use SymfonyBundleFrameworkBundleControllerController; use SymfonyComponentSecurityCoreSecurityContext; class SecurityController extends Controller { public function loginAction() { $request = $this->getRequest(); $session = $request->getSession();
  • 18. Controlador // obtiene el error de inicio de sesión si lo hay if ($request->attributes->has( SecurityContext::AUTHENTICATION_ERROR)) { $error = $request->attributes->get( SecurityContext::AUTHENTICATION_ERROR ); } else { $error = $session->get( SecurityContext::AUTHENTICATION_ERROR); $session->remove( SecurityContext::AUTHENTICATION_ERROR);
  • 19. Controlador } return $this->render( 'AcmeSecurityBundle:Security:login.html.twig', array( // último nombre de usuario ingresado 'last_username' => $session->get( SecurityContext::LAST_USERNAME), 'error' => $error, ) ); } }
  • 20. Controlador El trabajo es mostrar el formulario al usuario y los errores de ingreso que puedan haber ocurrido, el propio sistema de seguridad se encarga de verificar el nombre de usuario y contraseña y la autenticación del usuario.
  • 21. Plantilla {% if error %} <div>{{ error.message }}</div> {% endif %} <form action="{{ path('login_check') }}" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="_username" value="{{ last_username }}" /> <label for="password">Password:</label> <input type="password" id="password" name="_password" /> <button type="submit">login</button> </form>
  • 22. Plantilla Requisitos: Presentando el formulario a /login_check (a ​​través de la ruta login_check), el sistema de seguridad debe interceptar el envío del formulario y procesarlo automáticamente. El sistema de seguridad espera que los campos presentados se llamen _username y _password. Proceso: 1. Intenta acceder 2. El cortafuegos inicia la autenticación (/login) 3. /login reproduce el formulario 4. El usuario envía el formulario de acceso a /login_check 5. El sistema de seguridad intercepta la petición, comprueba las credenciales, autentica al usuario si todo está correcto, y si no, envía al usuario de nuevo al formulario de acceso.
  • 23. Evitando errores comunes 1. Crea las rutas correctas 2. Asegúrate de que la página de inicio de sesión no esté protegida 3. Asegúrate de que /login_check está detrás de un cortafuegos 4. Múltiples cortafuegos no comparten el contexto de seguridad
  • 24. Autorizando Una vez que el usuario se ha autenticado, comienza la autorización. La autorización proporciona una forma estándar y potente para decidir si un usuario puede acceder a algún recurso (una URL, un modelo de objetos, una llamada a un método, ...). Esto funciona asignando roles específicos a cada usuario y, a continuación, requiriendo diferentes roles para diferentes recursos.
  • 25. Protegiendo patrones de URL # app/config/security.yml security: # ... access_control: - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN } - { path: ^/admin, roles: ROLE_ADMIN } ^/admin/users /admin/users /users/admin
  • 26. Entendiendo como trabaja access_control Cada access_control tiene varias opciones que configuran dos diferentes cosas: (a) la petición entrante emparejada debe tener esta entrada de control de acceso y (b) una vez emparejada, debe tener algún tipo de restricción de acceso aplicable: # app/config/security.yml security: # ... access_control: - { path: ^/admin/users, roles: ROLE_SUPER_ADMIN } - { path: ^/admin, roles: ROLE_ADMIN }
  • 27. Emparejando opciones Symfony2 crea una instancia de SymfonyComponentHttpFoundationRequestMatcher para cada entrada access_control. Las siguientes opciones de access_control se utilizan para emparejar: ● path ● ip ● host ● methods
  • 28. Emparejando opciones # app/config/security.yml security: # ... access_control: - { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 } - { path: ^/admin, roles: ROLE_USER_HOST, host: symfony.com } - { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] } - { path: ^/admin, roles: ROLE_USER }
  • 29. 1. { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 } 2. { path: ^/admin, roles: ROLE_USER_HOST, host: symfony.com } 3. { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] } 4. { path: ^/admin, roles: ROLE_USER }
  • 30. 1. { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 } 2. { path: ^/admin, roles: ROLE_USER_HOST, host: symfony.com } 3. { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] } 4. { path: ^/admin, roles: ROLE_USER }
  • 31. 1. { path: ^/admin, roles: ROLE_USER_IP, ip: 127.0.0.1 } 2. { path: ^/admin, roles: ROLE_USER_HOST, host: symfony.com } 3. { path: ^/admin, roles: ROLE_USER_METHOD, methods: [POST, PUT] } 4. { path: ^/admin, roles: ROLE_USER }
  • 32. Forzando el acceso Al decidir que entrada access_control concuerda (si la hay), aplica las restricciones de acceso basándose en las opciones roles y requires_channel: ● role Si el usuario no tiene determinado rol o roles, entonces el acceso es denegado (internamente, se lanza una SymfonyComponentSecurityCoreExceptionAccessDenied Exception); ● requires_channel Si el canal de la petición entrante (p. ej. http) no concuerda con este valor (p. ej. https), el usuario será redirigido (p. ej. redirigido de http a https, o viceversa). Si el acceso es denegado, el sistema intentará autenticar al usuario si aún no lo está. Si el usuario ya inició sesión, se mostrará la página del error 403 «acceso denegado».
  • 33. Protegiendo por IP # app/config/security.yml security: # ... access_control: - { path: ^/esi, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 } - { path: ^/esi, roles: ROLE_NO_ACCESS }
  • 34. Protegiendo por canal # app/config/security.yml security: # ... access_control: - { path: ^/cart/checkout, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
  • 35. Protegiendo un controlador // ... use SymfonyComponentSecurityCoreExceptionAccessDeniedException; public function helloAction($name) { if (false === $this->get('security.context') ->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException(); } // ... }
  • 36. Protegiendo un controlador usando anotaciones // ... use JMSSecurityExtraBundleAnnotationSecure; /** * @Secure(roles="ROLE_ADMIN") */ public function helloAction($name) { // ... }
  • 37. Usuarios De donde provienen los usuarios? (Proveedores de usuarios) El usuario envía un conjunto de credenciales (username y password). El trabajo del sistema de autenticación es concordar esas credenciales contra una piscina de usuarios. Los usuarios pueden venir de cualquier parte. Todo lo que proporcione usuarios a la autenticación se llama «proveedor de usuario». Proveedores de usuario más comunes: Carga usuarios de un archivo de configuración. Carga usuarios de una tabla de la base de datos.
  • 38. Especificando usuarios en un archivo de configuración (en memoria) # app/config/security.yml security: # ... providers: default_provider: memory: users: ryan: { password: ryanpass, roles: 'ROLE_USER' } admin: { password: kitten, roles: 'ROLE_ADMIN' }
  • 39. Especificando usuarios en un archivo de configuración (en memoria) prudencia nombre de usuario utilizar la sintaxis alterna users: - { name: 77, password: pass, roles: 'ROLE_USER' } - { name: user-name, password: pass, roles: 'ROLE_USER' }
  • 40. Cargando usuarios de la base de datos Si deseas cargar tus usuarios a través del ORM de Doctrine, lo puedes hacer creando una clase User y configurando el proveedor entity.
  • 41. Restringiendo el acceso # app/config/security.yml security: firewalls: frontend: pattern: ^/* anonymous: ~ form_login: ~ access_control: - { path: ^/usuario/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
  • 42. Restringiendo el acceso - { path: ^/usuario/registro, roles: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/usuario/*, roles: ROLE_USUARIO } providers: usuarios: entity: { class: ClaseUsuarioBundleEntityUsuario, property: email } encoders: ClaseUsuarioBundleEntityUsuario: { algorithm: sha512, iterations: 10 }
  • 43. Creando la entidad usuario $ php app/console doctrine:generate:entity The Entity shortcut name: UsuarioBundle:Usuario Configuration format (yml, xml, php, or annotation) [annotation]: New field name (): nombre Field type [string]: <Enter> New field name (): apellidos Field type [string]: <Enter> New field name (): email Field type [string]: <Enter>
  • 44. New field name (): password Field type [string]: <Enter> New field name (): salt Field type [string]: <Enter> New field name (): <Enter> Do you want to generate an empty repository class [no]? no Do you confirm generation [yes]? yes
  • 45. Creando el proveedor de usuarios // src/Clase/UsuarioBundle/Entity/Usuario.php namespace ClaseUsuarioBundleEntity; use SymfonyComponentSecurityCoreUserUserInterface; use DoctrineORMMapping as ORM; /** * CuponUsuarioBundleEntityUsuario * * @ORMEntity */ class Usuario implements UserInterface { ... }
  • 46. // src/Clase/UsuarioBundle/Entity/Usuario.php class Usuario implements UserInterface { function eraseCredentials() {} function getRoles() { return array('ROLE_USUARIO'); } function getUsername() { return $this->getEmail(); } // ... }
  • 47. Implementar UserInterface • eraseCredentials(), se invoca cuando la aplicación necesita borrar la información más sensible del usuario, como por ejemplo su contraseña. • getPassword(), se invoca cada vez que la aplicación necesita obtener la contraseña del usuario. • getRoles(), cuando se autentica a un usuario, se invoca este método para obtener un array con todos los roles que posee. • getSalt(), devuelve el valor que se utilizó para aleatorizar la contraseña cuando se creó el usuario. • getUsername(), se invoca para obtener el login o nombre de usuario que se utiliza para autenticar a los usuarios.
  • 48. Añadiendo el formulario de login usuario_login: pattern: /usuario/login defaults: { _controller: UsuarioBundle:Default:login } usuario_login_check: pattern: /usuario/login_check usuario_logout: pattern: /usuario/logout
  • 49. Añadiendo el formulario de login • /login, se utiliza para mostrar el formulario de login. • /login_check, es la acción que comprueba que el usuario y contraseña introducidos son correctos. • /logout, se emplea para desconectar al usuario logueado.
  • 50. Actualizar ruta form_login # app/config/security.yml security: firewalls: frontend: pattern: ^/* anonymous: ~ form_login: login_path: /usuario/login check_path: /usuario/login_check login_path: usuario_login check_path: usuario_login_check
  • 51. El controlador //src/Clase/UsuarioBundle/Controller/DefaultController.php namespace ClaseUsuarioBundleController; use SymfonyBundleFrameworkBundleControllerController; use SymfonyComponentSecurityCoreSecurityContext; class DefaultController extends Controller { public function loginAction() { $peticion = $this->getRequest(); $sesion = $peticion->getSession(); $error = $peticion->attributes->get(
  • 53. La vista del formulario {# src/Clase/UsuarioBundle/Resources/views/Default/login.html.twig #} {% if error %} <div>{{ error.message }}</div> {% endif %} <form action="{{ path('usuario_login_check') }}" method="post"> <label for="username">Usuario:</label> <input type="text" id="username" name="_username" value="{{ last_username }}" /> <label for="password">Contraseña:</label> <input type="password" id="password" name="_password" /> <input type="submit" name="login" value="Acceder" /> </form>
  • 54. Formulario de registro #routing.yml usuario_registro: pattern: /registro defaults: { _controller: UsuarioBundle:Default:registro }
  • 55. Controlador registro // src/Clase/UsuarioBundle/Controller/DefaultController.php namespace ClaseUsuarioBundleController; use SymfonyBundleFrameworkBundleControllerController; use ClaseUsuarioBundleEntityUsuario; use ClaseUsuarioBundleFormFrontendUsuarioType; class DefaultController extends Controller { // ...
  • 56. Controlador registro public function registroAction() { $usuario = new Usuario(); $formulario = $this->createForm(new UsuarioType(), $usuario); return $this->render( 'UsuarioBundle:Default:registro.html.twig', array('formulario' => $formulario->createView()) ); } }
  • 57. Plantilla registro {# src/Clase/UsuarioBundle/Resources/views/Default/registro.html.twig #} <form action="{{ path('usuario_registro') }}" method="post" {{ form_enctype(formulario) }}> {{ form_widget(formulario) }} <input class="boton" type="submit" value="Registrarme" /> </form>
  • 58. Formulario registro // src/Clase/UsuarioBundle/Form/Frontend/UsuarioType.php namespace ClaseUsuarioBundleFormFrontend; use SymfonyComponentFormAbstractType; use SymfonyComponentFormFormBuilderInterface; use SymfonyComponentOptionsResolverOptionsResolverInterface; class UsuarioType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) {
  • 59. $builder ->add('nombre') ->add('apellidos') ->add('email', 'email') ->add('password', 'repeated', array( 'type' => 'password', 'invalid_message' => 'Las dos contraseñas deben coincidir', 'options' => array('label' => 'Contraseña') )) ; }
  • 60. public function setDefaultOptions (OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'ClaseUsuarioBundleEntityUsuario' )); } public function getName() { return 'clase_usuariobundle_usuariotype'; } }
  • 61. Controlador registro procesar form public function registroAction() { $peticion = $this->getRequest(); $usuario = new Usuario(); $formulario = $this->createForm(new UsuarioType(), $usuario); if ($peticion->getMethod() == 'POST') { $formulario->bind($peticion); if ($formulario->isValid()) { $encoder = $this->get('security.encoder_factory') ->getEncoder($usuario);
  • 63. $token = new UsernamePasswordToken( $usuario, $usuario->getPassword(), 'usuarios', $usuario->getRoles() ); $this->container ->get('security.context')->setToken($token); return $this->redirect($this->generateUrl('url')); }