以ajax格式包含Stripe卡信息会删除authenticity_token

问题描述 投票:0回答:3

我有一个使用Ajax的form_tag,以使用Stripe保存新的用户卡。它呈现Stripe卡形式,将输入传递给控制器​​方法,然后应提供js文件。它可以在没有Stripe内容的情况下工作,但是有了它,我遇到了身份验证问题。

这是基本代码:

<%= form_tag(save_card_path, id:'payment-form', remote: true) do %>
    <div id="card-element">
      <!-- A Stripe Element will be inserted here. -->
    </div>
  <button id="submit-card" class="submit-btn">Save Card</button>
<% end %>

<script type="text/javascript">

  var stripe = Stripe('<%= @stripe_public %>');
  var elements = stripe.elements();

  // Custom styling can be passed to options when creating an Element.
  var style = {
    base: {
      // Add your base input styles here. For example:
      fontSize: '20px',
      color: "#32325d",
    }
  };

  // Create an instance of the card Element.
  var card = elements.create('card', {style: style});

  // Add an instance of the card Element into the `card-element` <div>.
  card.mount('#card-element');

  card.addEventListener('change', function(event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
      displayError.textContent = event.error.message;
    } else {
      displayError.textContent = '';
    }
  });

  // Create a token or display an error when the form is submitted.
  var form = document.getElementById('payment-form');
  form.addEventListener('submit', function(event) {
    event.preventDefault();

    stripe.createToken(card).then(function(result) {
      if (result.error) {
        // Inform the customer that there was an error.
        var errorElement = document.getElementById('card-errors');
        errorElement.textContent = result.error.message;
      } else {
        // Send the token to your server.
        stripeTokenHandler(result.token);
      }
    });
  });

  function stripeTokenHandler(token) {
    // Insert the token ID into the form so it gets submitted to the server
    var form = document.getElementById('payment-form');
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'stripeToken');
    hiddenInput.setAttribute('value', token.id);
    form.appendChild(hiddenInput);

    // Submit the form
    form.submit();
  }
</script>

card_controller.rb

def save_card
  respond_to do |format|
    format.js
  end
end

save_card.js.erb

$("html").hide();

因此,就像我说的那样,没有Stripe代码,一切正常,并且参数中存在authenticity_token,但是我在上面编写的代码给出了以下错误:

    def handle_unverified_request
      raise ActionController::InvalidAuthenticityToken
    end

仅带有参数:

{"utf8"=>"✓", "stripeToken"=>"<token>"}

当我将选项authenticity_token: true添加到表单时,参数再次包含authenticity_token,但是现在当它到达format.js行时,我得到了错误

ActionController::UnknownFormat

在尝试通过Ajax上载表单文件时,我遇到了类似的问题,但是我发现了remotipart gem,并解决了该问题。但这在这种情况下似乎无济于事。

没有人知道为什么包括Stripe字段会摆脱我的authenticity_token,为什么即使有了authenticity_token,也无法识别js格式?


编辑:

Jquery-ujs通过我的//= require jquery_ujs中的行application.js包括在内,<%= csrf_meta_tags %>中的行包括在application.html.erb中,而我的源代码中包括了这些行

<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="<TOKEN>" />

无论我的ajax调用是否有效,都是这种情况。

更新:

这是我添加选项authenticity_token: true时的完整日志:

2020年12月20日00:07:04 +0100的127.0.0.1启动POST“ / save_card”

由UsersController#save_card作为HTML处理

参数:{“ utf8” =>“✓”,“ authenticity_token” =>“ [LONG TOKEN]”,“ post” =>“ 47”,“ transaction” =>“ bid”,“ stripeToken” =>“ [STRIPE令牌]”}

用户负载(0.9ms)

选择“用户”。*从“用户”,在“用户”。“ id” = $ 1排序依据“ users”。“ id” ASC LIMIT $ 2 [[“ id”,2],[“ LIMIT”,1]]

(0.3ms)开始SQL

((2.3ms)插入“卡片”(“ stripe_customer_id”,“品牌”,“ last4”,“ exp_month”,“ exp_year”,“ user_id”,“ created_at”,“ updated_at”)值($ 1,$ 2,$ 3,$ 4,$ 5,$ 6,$ 7,$ 8)返回“ id”[[“ stripe_customer_id”,“ [STRIPE TOKEN]”],[“ brand”,“ Visa”],[“ last4”,“ 4242”],[“ exp_month”,“ 4”],[“ exp_year”,“ 2024”],[“ user_id”,2],[“ created_at”,“ 2020-02-19 23:07:05.246789”],[“ updated_at”,“ 2020-02-19 23:07:05.246789”]]

((2.8ms)COMMIT

在672ms内完成406不可接受(ActiveRecord:6.3ms)

ActionController :: UnknownFormat(ActionController :: UnknownFormat):app / controllers / users_controller.rb:485:in'save_card'开始GET2020年2月20日00:07:05 +0100的127.0.0.1的“ /serviceworker.js”在2020-02-20 00:07:21 +0100上获取:: 1的“ /serviceworker.js”:>

这是我删除authenticity_token: true时的日志:

2020年12月20日00:33:17 +0100的127.0.0.1启动POST“ / save_card”

由UsersController#save_card作为HTML处理

参数:{“ utf8” =>“✓”,“ post” =>“ 47”,“ transaction” =>“ bid”,“ stripeToken” =>“ [STRIPE TOKEN]”}无法验证CSRF令牌真实性。 1毫秒内完成422个不可处理实体(ActiveRecord:0.0ms)

ActionController :: InvalidAuthenticityToken(ActionController :: InvalidAuthenticityToken):操作包(5.1.7)lib / action_controller / metal / request_forgery_protection.rb:195:inhandle_unverified_request' actionpack (5.1.7) lib/action_controller/metal/request_forgery_protection.rb:227:in handle_unverified_request'装置(4.7.0)lib / devise / controllers / helpers.rb:255:inhandle_unverified_request' actionpack (5.1.7) lib/action_controller/metal/request_forgery_protection.rb:222:in verify_authenticity_token'activesupport(5.1.7)lib / active_support / callbacks.rb:413:inblock in make_lambda' activesupport (5.1.7) lib/active_support/callbacks.rb:197:inblock(2级别”中止操作包(5.1.7)lib / abstract_controller / callbacks.rb:12:block (2 levels) in <module:Callbacks>' activesupport (5.1.7) lib/active_support/callbacks.rb:198:in中的“阻止”activesupport(5.1.7)lib / active_support / callbacks.rb:507:block in invoke_before' activesupport (5.1.7) lib/active_support/callbacks.rb:507:in每个'activesupport(5.1.7)lib / active_support / callbacks.rb:507:ininvoke_before' activesupport (5.1.7) lib/active_support/callbacks.rb:130:inrun_callbacks'actionpack(5.1.7)lib / abstract_controller / callbacks.rb:19:inprocess_action' actionpack (5.1.7) lib/action_controller/metal/rescue.rb:20:inprocess_action'动作包(5.1.7)lib / action_controller / metal / instrumentation.rb:32:inblock in process_action' activesupport (5.1.7) lib/active_support/notifications.rb:166:inblock in instrument'主动支持(5.1.7)lib / active_support / notifications / instrumenter.rb:21:在instrument' activesupport (5.1.7) lib/active_support/notifications.rb:166:in 仪器的操作包(5.1.7)中lib / action_controller / metal / instrumentation.rb:30:inprocess_action' actionpack (5.1.7) lib/action_controller/metal/params_wrapper.rb:252:inprocess_action'活动记录(5.1.7)lib / active_record / railties / controller_runtime.rb:22:inprocess_action' actionpack (5.1.7) lib/abstract_controller/base.rb:124:in流程的操作视图(5.1.7)lib / action_view / rendering.rb:30:process' actionpack (5.1.7) lib/action_controller/metal.rb:189:in中的“派遣”操作包(5.1.7)lib / action_controller / metal.rb:253:在dispatch' actionpack (5.1.7) lib/action_dispatch/routing/route_set.rb:49:in派遣'Actionpack中(5.1.7)lib / action_dispatch / routing / route_set.rb:31:serve' actionpack (5.1.7) lib/action_dispatch/journey/router.rb:50:in block中在发球动作包中(5.1.7)lib / action_dispatch / journey / router.rb:33:each' actionpack (5.1.7) lib/action_dispatch/journey/router.rb:33:in serve'actionpack(5.1.7)lib / action_dispatch / routing / route_set.rb:844:incall' serviceworker-rails (0.6.0) lib/serviceworker/middleware.rb:35:in call'remotipart(1.4.3)lib / remotipart / middleware.rb:32:in:call' warden (1.2.8) lib/warden/manager.rb:36:in block in call'warden(1.2.8)lib / warden / manager.rb:34:in catch' warden (1.2.8) lib/warden/manager.rb:34:in调用机架(2.0.7)lib / rack / etag.rb:25:incall' rack (2.0.7) lib/rack/conditional_get.rb:38:in通话架(2.0.7)lib / rack / head.rb:12:call' rack (2.0.7) lib/rack/session/abstract/id.rb:232:in context'机架(2.0.7)lib / rack / session / abstract / id.rb:226:在call' actionpack (5.1.7) lib/action_dispatch/middleware/cookies.rb:613:in中调用“ activerecord”(5.1.7)lib / active_record / migration.rb:556:incall' actionpack (5.1.7) lib/action_dispatch/middleware/callbacks.rb:26:inblock in呼叫'activesupport(5.1.7)lib / active_support / callbacks.rb:97:inrun_callbacks' actionpack (5.1.7) lib/action_dispatch/middleware/callbacks.rb:24:in通话'行动包(5.1.7)lib / action_dispatch / middleware / executor.rb:12:incall' actionpack (5.1.7) lib/action_dispatch/middleware/debug_exceptions.rb:59:incall'网络控制台(3.7.0)lib / web_console / middleware.rb:135:incall_app' web-console (3.7.0) lib/web_console/middleware.rb:30:inblock in调用“网络控制台(3.7.0)lib / web_console / middleware.rb:20:incatch' web-console (3.7.0) lib/web_console/middleware.rb:20:incall”动作包(5.1.7)lib / action_dispatch / middleware / show_exceptions.rb:31:在call' railties (5.1.7) lib/rails/rack/logger.rb:36:in call_app'轨道上(5.1.7)lib / rails / rack / logger.rb:24:inblock in call' activesupport (5.1.7) lib/active_support/tagged_logging.rb:69:inblock in tags'activesupport(5.1.7)lib / active_support / tagged_logging.rb:26:intagged' activesupport (5.1.7) lib/active_support/tagged_logging.rb:69:in被标记的“杂物”(5.1.7)lib / rails / rack / logger.rb:24:在call' sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in call'actionpack(5.1.7)中lib / action_dispatch / middleware / remote_ip.rb:79:在call' actionpack (5.1.7) lib/action_dispatch/middleware/request_id.rb:25:in调用机架中(2.0.7)lib / rack / method_override.rb:22:call' rack (2.0.7) lib/rack/runtime.rb:22:in中的调用“ activesupport”(5.1.7)lib / active_support / cache / strategy / local_cache_middleware.rb:27:incall' actionpack (5.1.7) lib/action_dispatch/middleware/executor.rb:12:in通话'行动包(5.1.7)lib / action_dispatch / middleware / static.rb:125:在call' rack (2.0.7) lib/rack/sendfile.rb:111:in call'栏杆中(5.1.7)lib / rails / engine.rb:522:incall' puma (3.12.1) lib/puma/configuration.rb:227:incall'puma(3.12.1)lib / puma / server.rb:660:inhandle_request' puma (3.12.1) lib/puma/server.rb:474:inprocess_client'puma(3.12.1)lib / puma / server.rb:334:在spawn_thread的block in run' puma (3.12.1) lib/puma/thread_pool.rb:135:in块中'开始GET2020年2月20日00:33:18 +0100的127.0.0.1的“ /serviceworker.js”

我有一个使用Ajax的form_tag,以使用Stripe保存新的用户卡。它呈现Stripe卡形式,将输入传递给控制器​​方法,然后应提供js文件。它不需要...

ruby-on-rails forms authentication stripe-payments csrf
3个回答
0
投票

您可以尝试以下操作吗,


0
投票

假设您在Rails 5.X上并且//= require rails-ujs文件中有application.js


0
投票

保留所有内容,然后更新.submit()

© www.soinside.com 2019 - 2024. All rights reserved.