Seguridad
Principios guía
Validación de formularios
Validación del cliente
Es preferible realizar una validación inicial en el lado del cliente para evitar enviar datos no válidos al servidor.
Ejemplo de creación de un formulario en la acción de un controlador (esta parte podría ubicarse en un servicio dedicado para una mejor separación de capas):
1 public function index(){
2 $frm=$this->jquery->semantic()->dataForm('frm-user',new User());
3 $frm->setFields(['login','password','connection']);
4 $frm->fieldAsInput('login',
5 ['rules'=>'empty']
6 );
7 $frm->fieldAsInput('password',
8 [
9 'inputType'=>'password',
10 'rules'=>['empty','minLength[6]']
11 ]
12 );
13 $frm->setValidationParams(['on'=>'blur','inline'=>true]);
14 $frm->fieldAsSubmit('connection','fluid green','/submit','#response');
15 $this->jquery->renderDefaultView();
16 }
La Vista Asociada:
{{ q['frm-user'] | raw }}
{{ script_foot | raw }}
<div id="response"></div>
Nota
Los controladores CRUD integran automáticamente esta validación del lado del cliente utilizando los validadores adjuntos a los miembros de los modelos.
#[Column(name: "password",nullable: true,dbType: "varchar(255)")]
#[Validator(type: "length",constraints: ["max"=>20,"min"=>6])]
#[Transformer(name: "password")]
private $password;
Validación en el servidor
Es preferible restringir las URL autorizadas a modificar los datos.
Previamente, especificando el método Http en las rutas, y probando la petición :
#[Post(path: "/submit")]
public function submitUser(){
if(!URequest::isCrossSite() && URequest::isAjax()){
$datas=URequest::getPost();//post with htmlEntities
//Do something with $datas
}
}
Nota
El módulo Ubiquity-security ofrece un control adicional para evitar las peticiones cross-site.
Tras modificar un objeto, es posible comprobar su validez, dados los validadores adjuntos a los miembros del Modelo asociado:
#[Post(path: "/submit")]
public function submitUser(){
if(!URequest::isCrossSite()){
$datas=URequest::getPost();//post with htmlEntities
$user=new User();
URequest::setValuesToObject($user,$datas);
$violations=ValidatorsManager::validate($user);
if(\count($violations)==0){
//do something with this valid user
} else {
//Display violations...
}
}
}
Operaciones DAO
- Siempre se recomienda utilizar consultas parametrizadas, independientemente de las operaciones que se realicen con los datos:
Para evitar inyecciones SQL.
Permitir el uso de consultas preparadas, acelerando el procesamiento.
$googleUsers=DAO::getAll(User::class,'email like ?',false,['%@gmail.com']);
$countActiveUsers=DAO::count(User::class,'active= ?',[true]);
Nota
Las operaciones DAO que toman objetos como parámetros utilizan este mecanismo por defecto.
DAO::save($user);
Gestión de contraseñas
El transformador Contraseña
permite que un campo sea de tipo contraseña cuando se muestra en un formulario CRUD generado automáticamente.
#[Transformer(name: "password")]
private $password;
Tras el envío desde un formulario, es posible encriptar una contraseña desde la clase URequest:
$encryptedPassword=URequest::password_hash('password');
$user->setPassword($encryptedPassword);
DAO::save($user);
El algoritmo utilizado en este caso está definido por el PASSWORD_DEFAULT
de php.
También es posible comprobar una contraseña introducida por un usuario del mismo modo, para compararla con un hash:
if(URequest::password_verify('password', $existingPasswordHash)){
//password is ok
}
Importante
Configure Https para evitar el envío de contraseñas en texto claro.
Módulo de seguridad/gestión ACL
- Además de estas pocas reglas, puede instalar si es necesario: