Symfony 3.3 FOSRestBundle + FOSUserBundle + PUGXMultiuserBundle Регистрация с почтальоном Защита CSRF недействительна
Я использую Symfony 3.3, я создаю свое приложение с FOSUserbundle и PUGXMultiuserBundle, и все в порядке. и теперь я пытаюсь создать свой API REST с FOSRestBundle, у меня возникла проблема, когда я пытаюсь зарегистрировать нового пользователя с почтальоном.
{
"code": 400,
"message": "Validation Failed",
"errors": {
"errors": [
"The CSRF token is invalid. Please try to resubmit the form."
],
"children": {
"email": {},
"username": {},
"plainPassword": {
"children": {
"first": {},
"second": {}
}
}
}
}
}
Я использовал этот пример для построения моего API REST, и это хорошо, но не работает с PUGXMultiuserBundle. Введите описание ссылки здесь.
а это мой класс для регистрации нового пользователя
<?php
namespace Taseera\EndpointBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use FOS\RestBundle\Controller\Annotations;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Routing\ClassResourceInterface;
use FOS\RestBundle\Controller\Annotations\RouteResource;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* @RouteResource("registration", pluralize=false)
*/
class RegistrationUserOneController extends FOSRestController implements ClassResourceInterface
{
/**
* @Annotations\Post("/register-company")
*/
public function registerAction(Request $request)
{
//$request = $this->getRequest();
$formFactory = $this->get('fos_user.registration.form.factory');
$form = $formFactory->createForm(array('csrf_protection' => false));
$discriminator = $this->container->get('pugx_user.manager.user_discriminator');
$discriminator->setClass('Taseera\UserBundle\Entity\UserOne');
$userManager = $this->container->get('pugx_user_manager');
$user = $userManager->createUser();
$dispatcher = $this->get('event_dispatcher');
$event = new GetResponseUserEvent($user, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
if (null !== $event->getResponse()) {
return $event->getResponse();
}
$form->setData($user);
$form->submit($request->request->all());
if ( ! $form->isValid()) {
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event);
if (null !== $response = $event->getResponse()) {
return $response;
}
return $form;
}
$event = new FormEvent($form, $request);
$dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
if ($event->getResponse()) {
return $event->getResponse();
}
$userManager->updateUser($user);
$response = new JsonResponse(
[
'msg' => $this->get('translator')->trans('registration.flash.user_created', [], 'FOSUserBundle'),
'token' => $this->get('lexik_jwt_authentication.jwt_manager')->create($user), // creates JWT
],
Response::HTTP_CREATED,
[
'Location' => $this->generateUrl(
'get_profile',
[ 'user' => $user->getId() ],
UrlGeneratorInterface::ABSOLUTE_URL
)
]
);
$dispatcher->dispatch(
FOSUserEvents::REGISTRATION_COMPLETED,
new FilterUserResponseEvent($user, $request, $response)
);
return $response;
}
}
я использую также "lexikjwt-authentication-bundle", "jms/serializer-bundle", "nelmio/api-doc-bundle" и "nelmio/cors-bundle"
это мой security.yml:
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_COMPANY]
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
admin:
pattern: ^/admin(.*)
form_login:
provider: fos_userbundle
login_path: admin_login
check_path: admin_login_check
# check_path verification de l'autentification
default_target_path: /admin
logout:
path: /admin/logout
target: /admin/login
anonymous: true
company:
pattern: ^/company(.*)
form_login:
provider: fos_userbundle
login_path: company_login
check_path: company_login_check
# check_path verification de l'autentification
default_target_path: /company/profile
logout:
path: /company/logout
target: /company/login
anonymous: true
main:
pattern: ^/
form_login:
provider: fos_userbundle
login_path: fos_user_security_login
check_path: fos_user_security_check
csrf_token_generator: security.csrf.token_manager
default_target_path: taseerafrontend_homepage
always_use_default_target_path: true
logout: true
anonymous: true
api:
pattern: ^/endpoint
stateless: true
lexik_jwt: ~
healthcheck:
pattern: ^/endpoint/ping$
anonymous: true
api_docs:
pattern: ^/endpoint/doc
anonymous: true
api_register:
pattern: ^/endpoint/register-company
anonymous: true
security: false
api_password_reset:
pattern: ^/endpoint/password/reset
anonymous: true
api_login:
pattern: ^/endpoint/login
stateless: true
anonymous: true
form_login:
check_path: /endpoint/login
require_previous_session: false
username_parameter: username
password_parameter: password
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
logout: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/endpoint/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/company/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/company/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/company/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/company/, role: ROLE_COMPANY }
и это мой config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed#https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: ar
category_directory: '%kernel.root_dir%/../web/backend/img/category'
user_one_company_directory: '%kernel.root_dir%/../web/backend/img/company'
medias_directory: '%kernel.root_dir%/../web/backend/img/medias'
framework:
#esi: ~
translator: ~
secret: '%secret%'
router:
resource: '%kernel.project_dir%/app/config/routing.yml'
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
default_locale: '%locale%'
trusted_hosts: ~
session:
# https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
handler_id: session.handler.native_file
save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
fragments: ~
http_method_override: true
assets: ~
php_errors:
log: true
# Twig Configuration
twig:
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
form_themes:
- 'bootstrap_3_layout.html.twig'
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
e.g. database_path: '%kernel.project_dir%/var/data/data.sqlite'
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
#path: '%database_path%'
orm:
auto_generate_proxy_classes: '%kernel.debug%'
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: '%mailer_transport%'
host: '%mailer_host%'
username: '%mailer_user%'
password: '%mailer_password%'
spool: { type: memory }
# app/config/config.yml
fos_user:
db_driver: orm # other valid values are 'mongodb' and 'couchdb'
firewall_name: main
user_class: Taseera\UserBundle\Entity\User
from_email:
address: "%mailer_user%"
sender_name: "%mailer_user%"
service:
user_manager: pugx_user_manager
registration:
confirmation:
enabled: true
change_password:
form:
type:
\UserBundle\Form\ChangePasswordFormType # or 'fos_user_change_password' on Symfony < 2.8
name: fos_user_company_change_password_form
validation_groups: [ChangePassword, Default]
#profile:
# form:
# type: Taseera\CompanyBundle\Form\ProfileFormType # or 'fos_user_profile' on Symfony < 2.8
# name: fos_user_company_profile
# validation_groups: [Profile, Default]
pugx_multi_user:
users:
user_one:
entity:
class: Taseera\UserBundle\Entity\UserOne
registration:
form:
type: Taseera\UserBundle\Form\Type\RegistrationUserOneFormType
name: fos_user_registration_form
validation_groups: [Registration, Default]
template: TaseeraUserBundle:Registration:user_one.form.html.twig
profile:
form:
type: Taseera\UserBundle\Form\ProfileUserOneFormType
name: fos_user_company_profile
validation_groups: [Profile, Default]
user_two:
entity:
class: Taseera\UserBundle\Entity\UserTwo
registration:
form:
type: Taseera\UserBundle\Form\Type\RegistrationUserTwoFormType
#name: fos_user_registration_form
validation_groups: [Registration, Default]
template: TaseeraUserBundle:Registration:user_two.form.html.twig
profile:
form:
type: Taseera\UserBundle\Form\ProfileUserTwoFormType
fos_rest:
body_listener: true
param_fetcher_listener: force
view:
view_response_listener: 'force'
formats:
json: true
xml: false
rss: false
mime_types:
json: ['application/json', 'application/x-json']
jpg: ['image/jpeg']
png: ['image/png']
routing_loader:
default_format: json
include_format: false
format_listener:
enabled: true
rules:
- { path: '^/endpoint', priorities: ['json', 'xml'], fallback_format: json, prefer_extension: true }
- { path: '^/', priorities: [ 'text/html', '*/*'], fallback_format: html, prefer_extension: true }
exception:
enabled: true
#JMS Serializer
jms_serializer: ~
# CSA Guzzle
csa_guzzle:
profiler: "%kernel.debug%"
# Lexik JWT Bundle
lexik_jwt_authentication:
private_key_path: "%jwt_private_key_path%"
public_key_path: "%jwt_public_key_path%"
pass_phrase: "%jwt_key_pass_phrase%"
token_ttl: "%jwt_token_ttl%"
# Nelmio CORS
nelmio_cors:
defaults:
allow_origin: ["%cors_allow_origin%"]
allow_methods: ["POST", "PUT", "GET", "DELETE", "OPTIONS"]
allow_headers: ["Content-Type", "Authorization"]
max_age: 3600
paths:
'^/': ~
# Nelmio API Doc
nelmio_api_doc: ~
1 ответ
Я нашел решение, и оно сработало для меня
я должен деактивировать csrf_protection в RegistrationUserOneFormType, относящемся к моей сущности UserOne, как это
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'csrf_protection' => false,
));
}