Si l' protect_from_forgery
option est mentionnée dans application_controller, alors je peux me connecter et effectuer toutes les requêtes GET, mais à la toute première requête POST, Rails réinitialise la session, ce qui me déconnecte.
J'ai protect_from_forgery
désactivé temporairement l' option, mais j'aimerais l'utiliser avec Angular.js. Y a-t-il un moyen de faire cela?
Réponses:
Je pense que lire la valeur CSRF à partir de DOM n'est pas une bonne solution, c'est juste une solution de contournement.
Voici un document du site officiel angularJS http://docs.angularjs.org/api/ng.$http :
Voici ma solution basée sur ces instructions:
Tout d'abord, définissez le cookie:
Ensuite, nous devons vérifier le jeton sur chaque requête non GET.
Puisque Rails a déjà construit avec la méthode similaire, nous pouvons simplement la remplacer pour ajouter notre logique:
la source
Si vous utilisez la protection Rails CSRF par défaut (
<%= csrf_meta_tags %>
), vous pouvez configurer votre module angulaire comme ceci:Ou, si vous n'utilisez pas CoffeeScript (quoi !?):
Si vous préférez, vous pouvez envoyer l'en-tête uniquement sur les demandes non GET avec quelque chose comme ce qui suit:
Assurez-vous également de consulter la réponse de HungYuHei , qui couvre toutes les bases sur le serveur plutôt que sur le client.
la source
<%= csrf_meta_tags %>
. J'ai pensé qu'il devrait y en avoir assez pour mentionnerprotect_from_forgery
seulement. Que faire? Le document de base doit être un simple HTML (je ne suis pas ici celui qui choisit).protect_from_forgery
ce que vous dites, c'est "lorsque mon code JavaScript fait des requêtes Ajax, je promets d'envoyer unX-CSRF-Token
dans l'en-tête qui correspond au jeton CSRF actuel". Afin d'obtenir ce jeton, Rails l'injecte dans le DOM avec<%= csrf_meta_token %>
et obtient le contenu de la balise meta avec jQuery chaque fois qu'il fait des requêtes Ajax (le pilote Rails 3 UJS par défaut le fait pour vous). Si vous n'utilisez pas ERB, il n'y a aucun moyen d'obtenir le jeton actuel de Rails dans la page et / ou le JavaScript - et vous ne pouvez donc pas l'utiliserprotect_from_forgery
de cette manière.csrf_meta_tags
chaque fois que le serveur génère une réponse, et chaque fois que ces balises sont différentes des précédentes. Ainsi, ces balises sont uniques pour chaque demande. La question est: comment l'application reçoit ces balises pour une requête AJAX (sans angulaire)? J'ai utilisé protect_from_forgery avec les requêtes jQuery POST, je ne me suis jamais soucié d'obtenir ce jeton CSRF, et cela a fonctionné. Comment?jQuery.ajaxPrefilter
comme indiqué ici: github.com/indirect/jquery-rails/blob/c1eb6ae/vendor/assets / ... Vous pouvez parcourir ce fichier et voir tous les cerceaux que Rails saute pour le faire fonctionner à peu près sans avoir à inquiétez-vous à ce sujet.put
etpost
au lieu decommon
? Du guide de sécurité des rails :The solution to this is including a security token in non-GET requests
La gemme angular_rails_csrf ajoute automatiquement le support du modèle décrit dans la réponse de HungYuHei à tous vos contrôleurs:
la source
angular_rails_csrf
gemme ne fonctionne pas avec Rails 5. Cependant, la configuration des en-têtes de requête Angular avec la valeur de la balise meta CSRF fonctionne!La réponse qui fusionne toutes les réponses précédentes et repose sur le fait que vous utilisez
Devise
une gemme d'authentification.Tout d'abord, ajoutez la gemme:
Ensuite, ajoutez un
rescue_from
bloc dans application_controller.rb:Et enfin, ajoutez le module intercepteur à votre application angulaire.
la source
$injector
au lieu de vous injecter directement$http
?J'ai vu les autres réponses et j'ai pensé qu'elles étaient excellentes et bien pensées. J'ai fait fonctionner mon application de rails avec ce que je pensais être une solution plus simple, alors j'ai pensé partager. Mon application rails est livrée avec ce paramètre par défaut,
J'ai lu les commentaires et il semblait que c'était ce que je voulais utiliser angular et éviter l'erreur csrf. Je l'ai changé en ceci,
Et maintenant ça marche! Je ne vois aucune raison pour laquelle cela ne devrait pas fonctionner, mais j'aimerais beaucoup entendre d'autres affiches.
la source
J'ai utilisé le contenu de la réponse de HungYuHei dans mon application. J'ai constaté que je rencontrais cependant quelques problèmes supplémentaires, certains à cause de mon utilisation de Devise pour l'authentification, et d'autres à cause du défaut que j'ai obtenu avec mon application:
Je note la question relative au dépassement de pile et les réponses , et j'ai écrit un article de blog beaucoup plus détaillé qui résume les différentes considérations. Les parties de cette solution qui sont pertinentes ici sont, dans le contrôleur d'application:
la source
J'ai trouvé un hack très rapide à cela. Tout ce que j'avais à faire est le suivant:
une. À mon avis, j'initialise une
$scope
variable qui contient le jeton, disons avant le formulaire, ou encore mieux à l'initialisation du contrôleur:b. Dans mon contrôleur AngularJS, avant d'enregistrer ma nouvelle entrée, j'ajoute le jeton au hachage:
Il n'y a plus rien à faire.
la source
Ça marche du côté angularjs!
la source