ActionController::InvalidAuthenticityToken in RegistrationsController#create

前端 未结 8 1449
后悔当初
后悔当初 2020-11-29 19:39

Hi I am using Devise for my user authentication suddenly my new user registration was not working.

this was error I am getting.

ActionController::In         


        
8条回答
  •  迷失自我
    2020-11-29 20:14

    TLDR: You are probably seeing this issue because your form submits via XHR.

    Few things first:

    1. Rails includes a CSRF token inside the head tag of your page.
    2. Rails evaluates this CSRF token anytime you perform a POST, PATCH or DELETE request.
    3. This token expires when you sign in or sign out

    A bog standard HTTP sign-in will cause a full page refresh, and the old CSRF token will be flushed and replaced with the brand new one that Rails creates when you sign in.

    An AJAX sign in will not refresh the page, so the crusty old, stale CSRF token, which is now invalid, is still present on your page.

    The solution is to update the CSRF token inside your HEAD tag manually after AJAX sign in.


    Some steps that I have shamelessly borrowed from a helpful thread on this matter.

    Step 1: Add the new CSRF-token to the response headers which are sent after a successful sign in

    class SessionsController < Devise::SessionsController
    
      after_action :set_csrf_headers, only: :create
    
      # ...
    
      protected
        def set_csrf_headers
          if request.xhr?
            # Add the newly created csrf token to the page headers
            # These values are sent on 1 request only
            response.headers['X-CSRF-Token'] = "#{form_authenticity_token}"
            response.headers['X-CSRF-Param'] = "#{request_forgery_protection_token}"
          end
        end
      end
    

    Step2: Use jQuery to update the page with the new values when the ajaxComplete event fires:

    $(document).on("ajaxComplete", function(event, xhr, settings) {
      var csrf_param = xhr.getResponseHeader('X-CSRF-Param');
      var csrf_token = xhr.getResponseHeader('X-CSRF-Token');
    
      if (csrf_param) {
        $('meta[name="csrf-param"]').attr('content', csrf_param);
      }
      if (csrf_token) {
        $('meta[name="csrf-token"]').attr('content', csrf_token);
      }
    });
    

    That's it. YMMV depending on your Devise configuration. I suspect though that this issue is ultimately caused by the fact that the old CSRF token is killing the request, and rails throws an exception.

提交回复
热议问题