【问题标题】:Rails: Completed 401 UnauthorizedRails:完成 401 Unauthorized
【发布时间】:2018-01-03 18:10:31
【问题描述】:

我收到此错误,但我不知道为什么。我特别排除了 CSRF 检查。 #webhook 方法有效,即使在生产中也是如此。其他类似的问题是关于设计的,但我没有在这个控制器中使用设计。

stripes_controller.rb
class StripesController < ApplicationController
  Stripe.api_key = ENV['STRIPE_PRIVATE']
  protect_from_forgery :except => [:webhook, :create]
  
  def show
  end

  def create
    # Amount in cents
    @amount = params[:amount]
  
    customer = Stripe::Customer.create(
      :email => params[:stripeEmail],
      :source  => params[:stripeToken]
    )
  
    charge = Stripe::Charge.create(
      :customer    => customer.id,
      :amount      => @amount,
      :description => 'Membership Fee',
      :currency    => 'usd'
    )
  
    render :show
  rescue Stripe::CardError => e
    flash[:error] = e.message
    redirect_to stripe_path
  end
routes.rb
resource :stripe do
Log
Started POST "/stripe/" for 127.0.0.1 at 2018-01-03 11:58:17 -0500
Processing by StripesController#create as HTML
  Parameters: {"amount"=>"100", "stripeToken"=>"tok_1BgFZ2IYOmXNPhc121HxNtw0", "stripeEmail"=>"test@example.com"}
  Rendering stripes/show.haml within layouts/application
  Rendered stripes/show.haml within layouts/application (2.0ms)
  User Load (3.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
   (2.0ms)  BEGIN
   (1.0ms)  COMMIT
Completed 401 Unauthorized in 3533ms (ActiveRecord: 6.0ms)


Started GET "/" for 127.0.0.1 at 2018-01-03 11:58:21 -0500

Rails 默认处于:debug 日志级别。 http://guides.rubyonrails.org/v5.0/debugging_rails_applications.html#log-levels

我可以通过设置来重现它

devise.rb
config.timeout_in = 1.minute # 8.hours

如果我已登录并处于活动状态,它可以正常工作,但如果会话超时,则会导致此 401 问题。

这是来自浏览器的请求/响应。它显示成功和 302 响应,而不是 401。但它在服务器控制台日志中显示 401。

POST /stripe/ HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Content-Length: 82
Cache-Control: max-age=0
Origin: http://localhost:3000
Content-Type: application/x-www-form-urlencoded
...

HTTP/1.1 302 Found
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Location: http://localhost:3000/
Content-Type: text/html; charset=utf-8

浏览器网络日志中没有一个 401 响应,即使按状态排序,即使使用 Preserver 日志也​​是如此。

Rails 5.0.2

【问题讨论】:

  • 您的application_controller 中有什么内容?
  • 我们需要查看StripesController#create整体,包括任何before_action/after_action 回调和ApplicationController 影响它/受到影响的操作由它。
  • 您可能在应用程序控制器中有 authenticate_user before_action。
  • @MarekLipka 这是application_controller.rb。但是,没有 before_actions 访问用户。
  • @ArtOfCode 我添加了整个#create,但它不访问用户。没有 before_actionafter_action 回调。

标签: ruby-on-rails


【解决方案1】:

HTTP 代码 401 Unauthorized 用于身份验证 (https://httpstatuses.com/401)。它与 CSRF 无关。在这种情况下,它会引发 ActionController::InvalidAuthenticityToken。

我很确定您的 ApplicationController 中有一个 before_action 需要用户身份验证(或在 routes.rb 中,或在 nginx/Apache 的配置中)。

【讨论】:

【解决方案2】:

按照 Marek 的建议,我将问题追踪到 user_signed_in?。该函数将HALT执行并发出 302 重定向,同时在服务器日志中打印 401!

devise.rb
config.timeout_in = 1.minute # 8.hours
stripes_controller.rb
class StripesController < ApplicationController
  layout false
show.haml
%h2 Thank you!
%p 
  Your payment of 
  %strong= number_to_currency(@amount.to_i * 0.01)
  has been received.
- if user_signed_in?
  Signed in
- else
  Signed out
  

如果用户已登录,页面将正常加载。如果用户的会话过期,那么 Devise 将重定向并设置一个 flash 消息

log
Started GET "/stripe" for 127.0.0.1 at 2018-01-03 14:39:08 -0500
Processing by StripesController#show as HTML
  Rendering stripes/show.haml
  User Load (22.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
   (1.0ms)  BEGIN
   (2.0ms)  COMMIT
  Rendered stripes/show.haml (179.2ms)
Completed 401 Unauthorized in 399ms (ActiveRecord: 52.0ms)


Started GET "/stripe" for 127.0.0.1 at 2018-01-03 14:39:09 -0500
Processing by StripesController#show as HTML
  Rendering stripes/show.haml
  Rendered stripes/show.haml (2.0ms)
Completed 200 OK in 219ms (Views: 99.8ms | ActiveRecord: 0.0ms)

我找不到一种方法来检查用户是否在没有重定向的情况下登录。

https://duckduckgo.com/?q=rails+devise+%22user_signed_in%22+stop+redirecting&ia=qa

user_signed_in? 在您搜索方法时甚至不在设计 API 文档中!我希望有一个可选参数。

http://www.rubydoc.info/github/plataformatec/devise/Devise

所以我设置了layout false,所以它停止使用包含user_signed_in?application.haml。我希望有更好的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 2013-02-22
    • 2017-01-13
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多