Rails, Devise authentication, CSRF issue

前端 未结 10 1146
不思量自难忘°
不思量自难忘° 2020-11-28 20:52

I\'m doing a singe-page application using Rails. When signing in and out Devise controllers are invoked using ajax. The problem I\'m getting is that when I 1) sign in 2) sig

10条回答
  •  囚心锁ツ
    2020-11-28 21:40

    Jimbo did an awesome job explaining the "why" behind the issue you're running into. There are two approaches you can take to resolve the issue:

    1. (As recommended by Jimbo) Override Devise::SessionsController to return the new csrf-token:

      class SessionsController < Devise::SessionsController
        def destroy # Assumes only JSON requests
          signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
          render :json => {
              'csrfParam' => request_forgery_protection_token,
              'csrfToken' => form_authenticity_token
          }
        end
      end
      

      And create a success handler for your sign_out request on the client side (likely needs some tweaks based on your setup, e.g. GET vs DELETE):

      signOut: function() {
        var params = {
          dataType: "json",
          type: "GET",
          url: this.urlRoot + "/sign_out.json"
        };
        var self = this;
        return $.ajax(params).done(function(data) {
          self.set("csrf-token", data.csrfToken);
          self.unset("user");
        });
      }
      

      This also assumes you're including the CSRF token automatically with all AJAX requests with something like this:

      $(document).ajaxSend(function (e, xhr, options) {
        xhr.setRequestHeader("X-CSRF-Token", MyApp.session.get("csrf-token"));
      });
      
    2. Much more simply, if it is appropriate for your application, you can simply override the Devise::SessionsController and override the token check with skip_before_filter :verify_authenticity_token.

提交回复
热议问题