CSRF Mismatch When POSTing from Ember to Sails Backend

First off, I just wanted to say that I have read through all of the other threads relating to this topic, but haven't had any luck. Here's a breakdown of the issue:

Goals

  • Retrieve a CSRF token from Sails when the Ember Application starts
  • Inject that CSRF token into every AJAX request that is initiated from the Ember Application
  • To satisfy goal 1, I created an Ember Initializer that runs when the application first boots up (if there is a better place for this, I'm totally open to suggestions). To satisfy goal 2, I retrieve the CSRF token from Sails and then attempt to use Ember.$.ajaxSetup() to ensure the CSRF token is passed either as a header ( X-CSRF-Token ) or parameter ( _csrf ). I also ensure that I'm using the withCredentials option to ensure the cookie is set. Here's the code:

    // initializers/csrf.js
    import Ember from 'ember';
    import config from '../config/environment';
    
    export function initialize() {
      Ember.$.get(config.APP.API_URL + '/csrfToken').then(function(result) {
        Ember.$.ajaxSetup({
          data: {
            '_csrf': result._csrf
          },
          xhrFields: { withCredentials: true }
        });
      }, function(error) {
        console.log(error);
      });
    }
    
    export default {
      name: 'csrf',
      initialize: initialize
    };
    

    All of this appears to work as I can see in Chrome dev tools that the CSRF token is being retrieved and when I make an AJAX request, I see the data appended to the POST data or added as a header (tried both options). Here's the code I'm running and all of the associated headers:

    Ember.$.post(config.APP.API_URL + '/auth/register', {
      'email': _this.get('email'),
      'password': _this.get('password')
    }).then(function(response) {
      console.log('It worked!');
    });
    

    Request Headers

    POST /auth/register HTTP/1.1
    Host: localhost:1337
    Connection: keep-alive
    Content-Length: 82
    Accept: */*
    Origin: http://localhost:4200
    CSP: active
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    DNT: 1
    Referer: http://localhost:4200/signup
    Accept-Encoding: gzip, deflate
    Accept-Language: en-US,en;q=0.8
    Cookie: sails.sid=s%3AbrABhErTY3-ytTWOKFJ2KBj7DCAzaLDc.apD60Sd%2BW85GSbTfJ7E3B2PrUwnhOsW6GlNpZTu9jFg
    

    Form Data

    _csrf:yP7GDiU2-YGmLBfBvQtMPT3-hRpnfK0x-AfA
    email:test@test.com
    password:q1w2e3r4
    

    Response Headers

    HTTP/1.1 403 Forbidden
    Vary: X-HTTP-Method-Override
    Access-Control-Allow-Origin: http://localhost:4200
    Access-Control-Allow-Credentials: true
    Content-Type: text/html; charset=utf-8
    Content-Length: 13
    Date: Thu, 09 Jul 2015 08:11:34 GMT
    Connection: keep-alive
    

    As you can see from the Response headers, I end up receiving a 403 Forbidden - CSRF Mismatch from Sails. Now, here's where it gets a little weird: first, I'm able to run this just fine with Postman. I retrieve a token and then post that token along with the data to the /auth/register url and it works as expected.

    I'm also tried removing the initializer and running the following code:

    Ember.$.ajaxSetup({
      xhrFields: { withCredentials: true }
    });
    
    Ember.$.get(config.APP.API_URL + '/csrfToken').then(function(result) {
      Ember.$.post(config.APP.API_URL + '/auth/register', {
        'email': _this.get('email'),
        'password': _this.get('password'),
        '_csrf': result._csrf
      }).then(function(response) {
        console.log('It worked!');
      });
    });
    

    This works. However, at this point, I'm at somewhat of a loss as to what the issue actually is. Appreciate any help I can get.

    Thanks in advance! James


    @jdixon04, Can you try URL-encoding the CSRF token before sending it through POST? The token mismatch will occur if the token is getting altered from the original.

    I found this issue in Github: https://github.com/balderdashy/sails/issues/2266.

    I hope this will solve your issue. Do try it and let me know if it works. Thanks.


    @jdixon04, got here from your post on my github issue. Actually, isn't the CSRF token going to change at each request made to the server? Then you approach to fix the token when the frontend load cannot cope with this, you may have to fetch the token before each request and use ajaxPrefilter to pass it to the request.

    Is that actually related to ember-data-sails? It seems to me you're doing pure ajax here! If you look in my config, you'll realise that pure ajax calls (for authentication as well) are exempted from csrf as I could not make it work as I wished : .


    像这样添加x-csrf-token标头:

    Ember.$.ajaxSetup({
      headers: {
        'X-CSRF-TOKEN': result._csrf
      },
      xhrFields: { withCredentials: true }
    });
    
    链接地址: http://www.djcxy.com/p/86576.html

    上一篇: rabbitmq中的例外与春季启动

    下一篇: 当从Ember发布到后端时,CSRF不匹配