Comment envoyer CSRF token () dans le formulaire AngularJS en utilisant L'API Laravel?

j'essaie de construire une application de repos angulaire + laravel. Je peux avoir les vues de ma base de données. Lorsque j'essaie d'ajouter de nouveaux éléments. Je reçois 500 error qui me dit que le jeton csrf ne correspond pas. La disposition de mon formulaire est:

<form class="form-horizontal" ng-submit="addItem()">

  <input type="text" ng-model="itemEntry" placeholder="Type and hit Enter to add item">
</form>

C'est ainsi que j'essaie d'ajouter un article à la base de données:

$scope.addItem = function(CSRF_TOKEN) {
    $http.post('/shop', { text: $scope.itemEntry, csrf_token: CSRF_TOKEN} ).success(function(data, status) {
        if(data) {
            var last = _.last($scope.items);
            _token = CSRF_TOKEN;
            $scope.items.push({text: $scope.itemEntry, bought: false, id: (last.id + 1) });
            $scope.itemEntry = '';
            console.log($scope.items);
        } else {
            console.log('There was a problem. Status: ' + status + '; Data: ' + data);
        }
    }).error(function(data, status) {
            console.log('status: ' + status);
        });

}

Voici mon filtre que j'utilise pour ma demande:

Route::filter('csrf', function()
{
    if (Session::token() != Input::get('_token'))
    {
        throw new IlluminateSessionTokenMismatchException;
    }
});

dans les vues de ma lame j'utilise ceci et cela fonctionne:

<input type="hidden" name="_token" value="{{ csrf_token() }}" />

Comment puis-je envoyer le csrf_token lorsque j'utilise des formulaires html?

Merci

Edit 1 : Ajouter un en-tête à une requête post comme celle-ci ne donne pas d'erreurs.

  $http({
    method  : 'POST',
    url     : '/shop',
    data    :  $scope.itemEntry,  // pass in data as strings
    headers : { 'Content-Type': 'application/x-www-form-urlencoded' }   
  });
20
demandé sur ytsejam 2013-08-20 17:45:37

4 réponses

une option sera d'injecter le jeton CSRF en tant que constante. Ajoutez ce qui suit à votre tête:

<script>
  angular.module("app").constant("CSRF_TOKEN", '{{ csrf_token() }}');
</script>

puis dans vos méthodes de module il peut être injecté si nécessaire.

app.factory("FooService", function($http, CSRF_TOKEN) {
    console.log(CSRF_TOKEN);
};

peut-être que vous serez intéressé de regarder le code source de ce échantillon Laravel + AngularJS projet .

27
répondu Rubens Mariuzzo 2013-08-20 15:09:24

la solution acceptée par Rubens Mariuzzo fonctionne, cependant je pense que j'ai trouvé une solution alternative qui je pense est meilleure.

de cette façon vous n'avez pas à passer des données du script html dans votre application angularjs et il y a une meilleure séparation des préoccupations. Par exemple: Cela vous permet d'avoir votre application Laravel comme une simple API.

ma solution consiste à obtenir le jeton CSRF via une requête api et à définir cette valeur comme une constante.

de plus, au lieu d'injecter le jeton CSRF si nécessaire, vous mettez le jeton dans un en-tête par défaut qui serait vérifié par le serveur sur n'importe quelle requête http API.

exemple montre laravel, cependant tout cadre sérieux devrait être en mesure d'offrir quelque chose de similaire.

CSRF Route in LARAVEL:

// Returns the csrf token for the current visitor's session.
Route::get('api/csrf', function() {
    return Session::token();
});

Protéger les Routes avec le before => 'api.csrf' Filtre

// Before making the declared routes available, run them through the api.csrf filter
Route::group(array('prefix' => 'api/v1', 'before' => 'api.csrf'), function() {
Route::resource('test1', 'Api\V1\Test1Controller');
Route::resource('test2', 'Api\V1\Test2Controller');
});

le api.csrf filtre

// If the session token is not the same as the the request header X-Csrf-Token, then return a 400 error.
Route::filter('api.csrf', function($route, $request)
{
if (Session::token() != $request->header('X-Csrf-Token') )
{
    return Response::json('CSRF does not match', 400);
}
});

les trucs AngularJS mettent ça dans app.js:

Blocage De La Version:

var xhReq = new XMLHttpRequest();
xhReq.open("GET", "//" + window.location.hostname + "/api/csrf", false);
xhReq.send(null);

app.constant("CSRF_TOKEN", xhReq.responseText);

app.run(['$http', 'CSRF_TOKEN', function($http, CSRF_TOKEN) {    
    $http.defaults.headers.common['X-Csrf-Token'] = CSRF_TOKEN;
}]);

Non Bloquant La Version

var xhReq = new XMLHttpRequest();
xhReq.open("GET", "//" + window.location.hostname + "/api/csrf", true);

xhReq.onload = function(e) {
  if (xhReq.readyState === 4) {
    if (xhReq.status === 200) {
      app.constant("CSRF_TOKEN", xhReq.responseText);

      app.run(['$http', 'CSRF_TOKEN', function($http, CSRF_TOKEN) {
        $http.defaults.headers.common['X-Csrf-Token'] = CSRF_TOKEN;
      }]);
    }
  }
};

xhReq.send(null);

maintenant la constante CSRF_TOKEN est injectée comme un en-tête dans toutes les requêtes http de L'application AngularJS et toutes les routes API sont protégées.

22
répondu Gravy 2015-05-07 10:19:14

si vous utilisez Laravel 5, pas besoin de pour ajouter un jeton CSRF à des en-têtes http angulaires.

Laravel 5 avec angle le font automatiquement pour vous.

http://laravel.com/docs/5.1/routing#csrf-x-xsrf-token

21
répondu Modder 2015-06-17 12:54:02

je pense que ma solution est moins de douleur et beaucoup plus flexible, surtout il pense tester votre application sur Karma.

ajoutez D'abord ce code votre vue de maître

 <meta name="csrf-token" content="{{ csrf_token() }}">

nous avons enregistré le jeton csrf dans le contenu html sans ajouter de route.

maintenant nous protégeons toutes les requêtes de L'application AngularJs par jeton CSRF

/**
 * 
 * when it thinks testing your app unit test with Karma,
 * this solution was better than getting token via AJAX.
 * Because low-level Ajax request correctly doesn't work on Karma
 * 
 * Helper idea to me :
 * /q/rails-csrf-protection-angular-js-protect-from-forgery-makes-me-to-log-out-on-post-50509/"csrf-token") {

            return  metas[i].content;       
        }
    }  

})();

// adding constant into our app

yourAngularApp.constant('CSRF_TOKEN', csrftoken); 

nous devons configurer les en-têtes http par défaut pour Angular. Ajoutons notre jeton csrf à Angulaire en-têtes

/*
 * App Configs
 */
blog.config(['$httpProvider', 'CSRF_TOKEN',

  function($httpProvider, CSRF_TOKEN) {


    /**
     * adds CSRF token to header
     */
    $httpProvider.defaults.headers.common['X-CSRF-TOKEN'] = CSRF_TOKEN;

 }]);

enfin nous avons besoin d'un nouveau filtre pour ces changements sur le côté de laravel..

Route::filter('csrfInHeader', function($route, $request) {

    if (Session::token() !== (string) $request->header('X-CSRF-TOKEN') ) {

        throw new Illuminate\Session\TokenMismatchException;

    }
});

"csrfInHeader" filtre va vérifier toutes les requête http par angulaire de l'app. Vous n'avez pas besoin d'ajouter un jeton csrf à chaque requête. De plus, si vous testez votre application par Karma, vous ne tenterez pas d'obtenir un jeton csrf sur testing..

6
répondu MURATSPLAT 2015-01-17 11:38:30