Angularjs Symfony2通过表单处理跨域请求

Angularjs Symfony2通过表单处理跨域请求,angularjs,forms,symfony,csrf,Angularjs,Forms,Symfony,Csrf,我有两个独立的项目:UI(AngularJS)和Server(Symfony2) 我需要从AngularJS应用程序向Symfony2应用程序发送跨域PUT请求 在Symfony控制器中,我将$request传递给表单->handleRequest()和调试告诉我,使用这种方式的表单不会被提交 因此,接下来我尝试将$request传递到表单->提交(),结果出现错误“无效的CSRF令牌” 如何通过Symfony表单正确处理跨域数据? 我已经读到,将$request传递给submit()方法是 去

我有两个独立的项目:UI(AngularJS)和Server(Symfony2)

我需要从AngularJS应用程序向Symfony2应用程序发送跨域PUT请求

在Symfony控制器中,我将
$request
传递给
表单->handleRequest()和调试告诉我,使用这种方式的表单不会被提交

因此,接下来我尝试将
$request
传递到
表单->提交()
,结果出现错误“无效的CSRF令牌”

  • 如何通过Symfony表单正确处理跨域数据? 我已经读到,将
    $request
    传递给submit()方法是 去润滑
  • 如果通过从UI发送CSRF令牌,如何将其传递到表单 标题?(我将csrf字段添加到请求中,但它不在后端处理)
  • 编辑:目前我发现该问题与CSRF令牌有关。无论我如何从UI发送这个令牌,它都不会在后端处理,并且我总是收到“无效CSRF令牌”错误

    我试图将\u token字段直接添加到json对象中,并通过
    csrf\u field\u name
    选项将字段名设置为\u token

    我还尝试将
    json\u decode($request->getContent(),true)
    传递给我的表单
    submit()
    方法,但调试后,我发现submittedData在下一个代码中发生了变化:

    // Symfony/Component/Form/Form.php, submit() method
    
    if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) {
        // here submittedData has csrf _token key/value
        $event = new FormEvent($this, $submittedData);
        $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event);
        $submittedData = $event->getData();
        // now submittedData without _token key/value
    }
    
    编辑2:更多详细信息
    CsrfValidationListener
    使用Symfony表单组件调用
    this->tokenManager->isTokenValid(新的CsrfToken($this->tokenId,$data[$this->fieldName])
    返回false,下一个代码中的问题:

    // Symfony/Component/Security/Csrf/CsrfTokenManager.php
    
    public function isTokenValid(CsrfToken $token)
        {
            if (!$this->storage->hasToken($token->getId())) {
                return false;
            }
    
            return StringUtils::equals($this->storage->getToken($token->getId()), $token->getValue());
        }
    
    csrf令牌似乎存储在会话中,因此
    isTokenValid()
    方法返回
    false

    我继续调试

    编辑3

    如我所见,从CsrfTokenManager.php调用
    $this->storage->hasToken($token->getId())
    时,会话为空

    这很奇怪,因为我用下一种方式从控制器生成csrf令牌:

    $csrfToken = $this->get('security.csrf.token_manager')->refreshToken('Symfony');
    
    如我所见,refreshToken()方法将csrf令牌保存到db中:

    // Csrf/CsrfTokenManager.php
    public function refreshToken($tokenId)
        {
            $value = $this->generator->generateToken();
    
            $this->storage->setToken($tokenId, $value);
    
            return new CsrfToken($tokenId, $value);
        }
    // Csrf/TokenStorage/SessionTokenStorage.php
    public function setToken($tokenId, $token)
        {
            if (!$this->session->isStarted()) {
                $this->session->start();
            }
    
            $this->session->set($this->namespace.'/'.$tokenId, (string) $token);
        }
    
    但是当我向表单发送数据时,
    this->tokenManager->isTokenValid(新的CsrfToken($this->tokenId,$data[$this->fieldName]))
    调用
    CsrfValidationListener
    的preSubmit()方法返回空会话

    为了防止我添加security.yml设置,可能我遗漏了一些内容:

    main:
        pattern: ^/(?!login).+
        stateless: true
        simple_preauth:
            authenticator: app_bundle.api_key_authenticator
        provider: api_key_user_provider
        anonymous: ~
        logout: ~
    
    login:
        pattern: ^/login
        stateless: false
        simple_preauth:
            authenticator: app_bundle.email_password_authenticator
        provider: email_user_provider
        anonymous: ~
    
    注意:我在登录防火墙下生成csrf令牌,并尝试从主防火墙访问它

    但我也尝试在同一个防火墙中生成csrf令牌。没有什么变化

    编辑4

    我已经为跟踪会话创建配置了自定义会话目录。所以,我可以看到,在登录时,我有一个具有所有属性的会话,但当我执行PUT请求时,我注意到创建了新的会话文件,它包含如下内容:

    _sf2_attributes|a:0:{}_sf2_flashes|a:0:{}_sf2_meta|a:3:{s:1:"u";i:1449700968;s:1:"c";i:1449700968;s:1:"l";s:1:"0";}
    

    只是空会话。

    因此,我找到了csrf错误行为的原因

    创建csrf令牌时,它存储到会话中。因为我的api防火墙是无状态的,它不能存储csrf令牌。并且在每个身份验证会话上都是drop,并且只有当前的身份验证令牌

    正确配置的CORS有助于防止csrf攻击

    另见


    希望,这将对某些人有所帮助。

    因此,我找到了csrf错误行为的原因

    创建csrf令牌时,它存储到会话中。因为我的api防火墙是无状态的,它不能存储csrf令牌。并且在每个身份验证会话上都是drop,并且只有当前的身份验证令牌

    正确配置的CORS有助于防止csrf攻击

    另见


    希望,这将对某些人有所帮助。

    是否要禁用csrf保护?@Matteo no,我认为最好离开csrf。。我想和CORSdo一起使用你想禁用csrf保护吗?@Matteo不,我想最好还是离开csrf。。我想和CORS一起使用