Controladores de autenticación (Auth Controllers)
- Los controladores Auth permiten realizar una autentificación básica con:
iniciar sesión con una cuenta
creación de cuenta
cierre de sesión
controladores con autenticación requerida
Creación
En la interfaz de administración (web-toolsb), active la parte Controllers y seleccione crear Auth controller:
- A continuación, rellene el formulario:
Introduzca el nombre del controlador (BaseAuthController en este caso)
El controlador generado:
1 /**
2 * Auth Controller BaseAuthController
3 **/
4class BaseAuthController extends \Ubiquity\controllers\auth\AuthController{
5
6 protected function onConnect($connected) {
7 $urlParts=$this->getOriginalURL();
8 USession::set($this->_getUserSessionKey(), $connected);
9 if(isset($urlParts)){
10 Startup::forward(implode("/",$urlParts));
11 }else{
12 //TODO
13 //Forwarding to the default controller/action
14 }
15 }
16
17 protected function _connect() {
18 if(URequest::isPost()){
19 $email=URequest::post($this->_getLoginInputName());
20 $password=URequest::post($this->_getPasswordInputName());
21 //TODO
22 //Loading from the database the user corresponding to the parameters
23 //Checking user creditentials
24 //Returning the user
25 }
26 return;
27 }
28
29 /**
30 * {@inheritDoc}
31 * @see \Ubiquity\controllers\auth\AuthController::isValidUser()
32 */
33 public function _isValidUser($action=null): bool {
34 return USession::exists($this->_getUserSessionKey());
35 }
36
37 public function _getBaseRoute(): string {
38 return 'BaseAuthController';
39 }
40}
Aplicación de la autentificación
Ejemplo de implementación con la interfaz de administración : Añadiremos una comprobación de autenticación en la interfaz de administración.
La autenticación se basa en la verificación del par correo electrónico/contraseña de un modelo User:
Modificación de BaseAuthController
1 /**
2 * Auth Controller BaseAuthController
3 **/
4class BaseAuthController extends \Ubiquity\controllers\auth\AuthController{
5
6 protected function onConnect($connected) {
7 $urlParts=$this->getOriginalURL();
8 USession::set($this->_getUserSessionKey(), $connected);
9 if(isset($urlParts)){
10 Startup::forward(implode("/",$urlParts));
11 }else{
12 Startup::forward("admin");
13 }
14 }
15
16 protected function _connect() {
17 if(URequest::isPost()){
18 $email=URequest::post($this->_getLoginInputName());
19 $password=URequest::post($this->_getPasswordInputName());
20 return DAO::uGetOne(User::class, "email=? and password= ?",false,[$email,$password]);
21 }
22 return;
23 }
24
25 /**
26 * {@inheritDoc}
27 * @see \Ubiquity\controllers\auth\AuthController::isValidUser()
28 */
29 public function _isValidUser($action=null): bool {
30 return USession::exists($this->_getUserSessionKey());
31 }
32
33 public function _getBaseRoute(): string {
34 return 'BaseAuthController';
35 }
36 /**
37 * {@inheritDoc}
38 * @see \Ubiquity\controllers\auth\AuthController::_getLoginInputName()
39 */
40 public function _getLoginInputName(): string {
41 return "email";
42 }
43}
Modificación del controlador de administración
Modificar el controlador de administración para utilizar BaseAuthController:
1class Admin extends UbiquityMyAdminBaseController{
2 use WithAuthTrait;
3 protected function getAuthController(): AuthController {
4 return $this->_auth ??= new BaseAuthController($this);
5 }
6}
Pruebe la interfaz de administración en /admin:
Después de hacer clic en login:
Si los datos de autenticación introducidos no son válidos:
Si los datos de autenticación introducidos son válidos:
Adjuntar la zona info-user
Modificar el controlador BaseAuthController:
1 /**
2 * Auth Controller BaseAuthController
3 **/
4class BaseAuthController extends \Ubiquity\controllers\auth\AuthController{
5...
6 public function _displayInfoAsString(): bool {
7 return true;
8 }
9}
El área _userInfo está ahora presente en todas las páginas de la administración:
Puede mostrarse en cualquier plantilla twig:
{{ _userInfo | raw }}
Descripción de las características
Personalización de plantillas
plantilla index.html
La plantilla index.html gestiona la conexión:
Ejemplo con el área _userInfo:
Cree un nuevo AuthController llamado PersoAuthController:
Editar la plantilla app/views/PersoAuthController/info.html
1{% extends "@framework/auth/info.html" %}
2{% block _before %}
3 <div class="ui tertiary inverted red segment">
4{% endblock %}
5{% block _userInfo %}
6 {{ parent() }}
7{% endblock %}
8{% block _logoutButton %}
9 {{ parent() }}
10{% endblock %}
11{% block _logoutCaption %}
12 {{ parent() }}
13{% endblock %}
14{% block _loginButton %}
15 {{ parent() }}
16{% endblock %}
17{% block _loginCaption %}
18 {{ parent() }}
19{% endblock %}
20{% block _after %}
21 </div>
22{% endblock %}
Cambiar el controlador AuthController Admin:
1class Admin extends UbiquityMyAdminBaseController{
2 use WithAuthTrait;
3 protected function getAuthController(): AuthController {
4 return $this->_auth ??= new PersoAuthController($this);
5 }
6}
Personalización de los mensajes
1class PersoAuthController extends \controllers\BaseAuth{
2...
3 /**
4 * {@inheritDoc}
5 * @see \Ubiquity\controllers\auth\AuthController::badLoginMessage()
6 */
7 protected function badLoginMessage(\Ubiquity\utils\flash\FlashMessage $fMessage) {
8 $fMessage->setTitle("Erreur d'authentification");
9 $fMessage->setContent("Login ou mot de passe incorrects !");
10 $this->_setLoginCaption("Essayer à nouveau");
11
12 }
13...
14}
Conexión de autocomprobación
1class PersoAuthController extends \controllers\BaseAuth{
2...
3 /**
4 * {@inheritDoc}
5 * @see \Ubiquity\controllers\auth\AuthController::_checkConnectionTimeout()
6 */
7 public function _checkConnectionTimeout() {
8 return 10000;
9 }
10...
11}
Limitación de los intentos de conexión
1class PersoAuthController extends \controllers\BaseAuth{
2...
3 /**
4 * {@inheritDoc}
5 * @see \Ubiquity\controllers\auth\AuthController::attemptsNumber()
6 */
7 protected function attemptsNumber(): int {
8 return 3;
9 }
10...
11}
Recuperación de cuenta
La recuperación de cuenta se utiliza para restablecer la contraseña de la cuenta.
Se envía un correo electrónico de restablecimiento de contraseña, a una dirección de correo electrónico correspondiente a una cuenta activa.
1class PersoAuthController extends \controllers\BaseAuth{
2...
3 protected function hasAccountRecovery():bool{
4 return true;
5 }
6
7 protected function _sendEmailAccountRecovery(string $email,string $validationURL,string $expire):bool {
8 MailerManager::start();
9 $mail=new AuthAccountRecoveryMail();
10 $mail->to($connected->getEmail());
11 $mail->setUrl($validationURL);
12 $mail->setExpire($expire);
13 return MailerManager::send($mail);
14 }
15
16 protected function passwordResetAction(string $email,string $newPasswordHash):bool {
17 //To implement for modifying the user password
18 }
19
20 protected function isValidEmailForRecovery(string $email):bool {
21 //To implement: return true if a valid account match with this email
22 }
23}
Nota
Por defecto, el enlace sólo puede utilizarse en la misma máquina, dentro de un periodo de tiempo predeterminado (que puede modificarse anulando el método accountRecoveryDuration
).
Activación de MFA/2FA
La autenticación multifactor puede activarse condicionalmente, en función de la información del usuario previamente registrado.
Nota
La fase 2 de la autenticación se realiza en el siguiente ejemplo enviando un código aleatorio por correo electrónico. La clase AuthMailerClass está disponible en el paquete Ubiquity-mailer
.
1class PersoAuthController extends \controllers\BaseAuth{
2...
3 /**
4 * {@inheritDoc}
5 * @see \Ubiquity\controllers\auth\AuthController::has2FA()
6 */
7 protected function has2FA($accountValue=null):bool{
8 return true;
9 }
10
11 protected function _send2FACode(string $code, $connected):void {
12 MailerManager::start();
13 $mail=new AuthMailerClass();
14 $mail->to($connected->getEmail());
15 $mail->setCode($code);
16 MailerManager::send($mail);
17 }
18...
19}
Nota
Es posible personalizar la creación del código generado, así como el prefijo utilizado. El ejemplo de abajo está implementado con la librería robthree/twofactorauth
.
protected function generate2FACode():string{
$tfa=new TwoFactorAuth();
return $tfa->createSecret();
}
protected function towFACodePrefix():string{
return 'U-';
}
Creación de cuenta
La activación de la creación de la cuenta también es opcional:
1class PersoAuthController extends \controllers\BaseAuth{
2...
3 protected function hasAccountCreation():bool{
4 return true;
5 }
6...
7}
En este caso, debe sobrescribirse el método _create para crear la cuenta:
protected function _create(string $login, string $password): ?bool {
if(!DAO::exists(User::class,'login= ?',[$login])){
$user=new User();
$user->setLogin($login);
$user->setPassword($password);
URequest::setValuesToObject($user);//for the others params in the POST.
return DAO::insert($user);
}
return false;
}
Puede comprobar la validez/disponibilidad del login antes de validar el formulario de creación de cuenta:
protected function newAccountCreationRule(string $accountName): ?bool {
return !DAO::exists(User::class,'login= ?',[$accountName]);
}
Se puede solicitar al usuario una acción de confirmación (verificación por correo electrónico):
protected function hasEmailValidation(): bool {
return true;
}
protected function _sendEmailValidation(string $email,string $validationURL,string $expire):void {
MailerManager::start();
$mail=new AuthEmailValidationMail();
$mail->to($connected->getEmail());
$mail->setUrl($validationURL);
$mail->setExpire($expire);
MailerManager::send($mail);
}
Nota
Es posible personalizar estas partes anulando los métodos asociados o modificando las interfaces en las plantillas correspondientes.