php - node - security symfony2
Eliminar/Reemplazar el campo de nombre de usuario con correo electrónico usando FOSUserBundle en Symfony2/Symfony3 (7)
Solo quiero tener un correo electrónico como modo de inicio de sesión, no quiero tener un nombre de usuario. ¿Es posible con Symfony2 / symfony3 y FOSUserbundle?
Leo aquí http://groups.google.com/group/symfony2/browse_thread/thread/92ac92eb18b423fe
Pero luego estoy atascado con dos violaciones de restricción.
El problema es que si el usuario deja en blanco la dirección de correo electrónico, recibo dos infracciones de restricciones:
- por favor, ingrese un nombre de usuario
- Por favor ingrese un correo electrónico
¿Hay alguna manera de desactivar la validación de un campo determinado o una forma mejor de eliminar un campo del formulario por completo?
Una descripción completa de lo que se debe hacer
Aquí hay una descripción completa de lo que debe hacerse. He enumerado las diferentes fuentes que se encuentran aquí y allá al final de esta publicación.
1. Anular setter en Acme/UserBundle/Entity/User
public function setEmail($email)
{
$email = is_null($email) ? '''' : $email;
parent::setEmail($email);
$this->setUsername($email);
return $this;
}
2. Eliminar el campo de nombre de usuario de su tipo de formulario
(en RegistrationFormType
y ProfileFormType
)
public function buildForm(FormBuilder $builder, array $options)
{
parent::buildForm($builder, $options);
$builder->remove(''username''); // we use email as the username
//..
}
3. Restricciones de validación
Como se muestra en @nurikabe, tenemos que deshacernos de las restricciones de validación provistas por FOSUserBundle
y crear las nuestras propias. Esto significa que tendremos que volver a crear todas las restricciones que se crearon previamente en FOSUserBundle
y eliminar las que se refieren al campo de username
. Los nuevos grupos de validación que AcmeRegistration
son AcmeRegistration
y AcmeProfile
. Por lo tanto, estamos anulando por completo los proporcionados por FOSUserBundle
.
3.a. Actualizar el archivo de configuración en Acme/UserBundle/Resources/config/config.yml
fos_user:
db_driver: orm
firewall_name: main
user_class: Acme/UserBundle/Entity/User
registration:
form:
type: acme_user_registration
validation_groups: [AcmeRegistration]
profile:
form:
type: acme_user_profile
validation_groups: [AcmeProfile]
3.b. Crear el archivo de validación Acme/UserBundle/Resources/config/validation.yml
Ese es el largo plazo:
Acme/UserBundle/Entity/User:
properties:
# Your custom fields in your user entity, here is an example with FirstName
firstName:
- NotBlank:
message: acme_user.first_name.blank
groups: [ "AcmeProfile" ]
- Length:
min: 2
minMessage: acme_user.first_name.short
max: 255
maxMessage: acme_user.first_name.long
groups: [ "AcmeProfile" ]
# Note: We still want to validate the email
# See FOSUserBundle/Resources/config/validation/orm.xml to understand
# the UniqueEntity constraint that was originally applied to both
# username and email fields
#
# As you can see, we are only applying the UniqueEntity constraint to
# the email field and not the username field.
FOS/UserBundle/Model/User:
constraints:
- Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity:
fields: email
errorPath: email
message: fos_user.email.already_used
groups: [ "AcmeRegistration", "AcmeProfile" ]
properties:
email:
- NotBlank:
message: fos_user.email.blank
groups: [ "AcmeRegistration", "AcmeProfile" ]
- Length:
min: 2
minMessage: fos_user.email.short
max: 255
maxMessage: fos_user.email.long
groups: [ "AcmeRegistration", "ResetPassword" ]
- Email:
message: fos_user.email.invalid
groups: [ "AcmeRegistration", "AcmeProfile" ]
plainPassword:
- NotBlank:
message: fos_user.password.blank
groups: [ "AcmeRegistration", "ResetPassword", "ChangePassword" ]
- Length:
min: 2
max: 4096
minMessage: fos_user.password.short
groups: [ "AcmeRegistration", "AcmeProfile", "ResetPassword", "ChangePassword"]
FOS/UserBundle/Model/Group:
properties:
name:
- NotBlank:
message: fos_user.group.blank
groups: [ "AcmeRegistration" ]
- Length:
min: 2
minMessage: fos_user.group.short
max: 255
maxMessage: fos_user.group.long
groups: [ "AcmeRegistration" ]
FOS/UserBundle/Propel/User:
properties:
email:
- NotBlank:
message: fos_user.email.blank
groups: [ "AcmeRegistration", "AcmeProfile" ]
- Length:
min: 2
minMessage: fos_user.email.short
max: 255
maxMessage: fos_user.email.long
groups: [ "AcmeRegistration", "ResetPassword" ]
- Email:
message: fos_user.email.invalid
groups: [ "AcmeRegistration", "AcmeProfile" ]
plainPassword:
- NotBlank:
message: fos_user.password.blank
groups: [ "AcmeRegistration", "ResetPassword", "ChangePassword" ]
- Length:
min: 2
max: 4096
minMessage: fos_user.password.short
groups: [ "AcmeRegistration", "AcmeProfile", "ResetPassword", "ChangePassword"]
FOS/UserBundle/Propel/Group:
properties:
name:
- NotBlank:
message: fos_user.group.blank
groups: [ "AcmeRegistration" ]
- Length:
min: 2
minMessage: fos_user.group.short
max: 255
maxMessage: fos_user.group.long
groups: [ "AcmeRegistration" ]
4. Fin
¡Eso es! ¡Usted debe ser bueno para ir!
Documentos utilizados para esta publicación:
¿Has intentado personalizar la validación?
Para hacer esto, necesita tener su propio paquete heredando del UserBundle, y luego copiar / ajustar Resources / config / validation.xml. Además, debe configurar validation_groups en config.yml en su validación personalizada.
A partir de Sf 2.3, una solución rápida es establecer el nombre de usuario en cualquier cadena en la construcción de su clase Usuario que extiende BaseUser.
public function __construct()
{
parent::__construct();
$this->username = ''username'';
}
De esta manera, el validador no desencadenará ninguna violación. Pero no olvides configurar el correo electrónico con el nombre de usuario publicado por Patt .
public function setEmail($email)
{
$email = is_null($email) ? '''' : $email;
parent::setEmail($email);
$this->setUsername($email);
}
Es posible que deba verificar otros archivos para obtener referencias de Usuario: nombre de usuario y cambiar en consecuencia.
Como señala Michael, esto se puede resolver con un grupo de validación personalizado. Por ejemplo:
fos_user:
db_driver: orm
firewall_name: main
user_class: App/UserBundle/Entity/User
registration:
form:
type: app_user_registration
validation_groups: [AppRegistration]
Luego, en su entidad (según lo definido por user_class: App/UserBundle/Entity/User
) puede usar el grupo AppRegistration:
class User extends BaseUser {
/**
* Override $email so that we can apply custom validation.
*
* @Assert/NotBlank(groups={"AppRegistration"})
* @Assert/MaxLength(limit="255", message="Please abbreviate.", groups={"AppRegistration"})
* @Assert/Email(groups={"AppRegistration"})
*/
protected $email;
...
Esto es lo que terminé haciendo después de publicar esa respuesta al hilo de Symfony2.
Consulte http://symfony.com/doc/2.0/book/validation.html#validation-groups para obtener más información.
En lugar de reemplazar la Validación, prefiero reemplazar el proceso RegistrationFormHandler #, agregar con mayor precisión el nuevo método processExtended (por ejemplo), que es una copia del método original, y usar ut en RegistrationController. (Anulación: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md#next-steps )
Antes de vincular el formulario de registro, configuro un nombre de usuario para, por ejemplo, ''vacío'':
class RegistrationFormHandler extends BaseHandler
{
public function processExtended($confirmation = false)
{
$user = $this->userManager->createUser();
$user->setUsername(''empty''); //That''s it!!
$this->form->setData($user);
if (''POST'' == $this->request->getMethod()) {
$this->form->bindRequest($this->request);
if ($this->form->isValid()) {
$user->setUsername($user->getEmail()); //set email as username!!!!!
$this->onSuccess($user, $confirmation);
/* some my own logic*/
$this->userManager->updateUser($user);
return true;
}
}
return false;
}
// replace other functions if you want
}
¿Por qué? Prefiero usar las reglas de validación de FOSUserBundle. Porque si reemplazo Validation Group en config.yml para el formulario de registro, necesito repetir las reglas de validación para el usuario en mi propia entidad de usuario.
Pude hacer esto anulando el tipo de formulario de registro y perfil detallado here y eliminando el campo de nombre de usuario
$builder->remove(''username'');
Junto con anular el método setEmail en mi clase de usuario concreta:
public function setEmail($email)
{
$email = is_null($email) ? '''' : $email;
parent::setEmail($email);
$this->setUsername($email);
}
Si ninguno de ellos funciona, una solución rápida y sucia sería
public function setEmail($email)
{
$email = is_null($email) ? '''' : $email;
parent::setEmail($email);
$this->setUsername(uniqid()); // We do not care about the username
return $this;
}