Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 使用简单令牌登录后,rails将重定向到referer域_Ruby On Rails_Devise - Fatal编程技术网

Ruby on rails 使用简单令牌登录后,rails将重定向到referer域

Ruby on rails 使用简单令牌登录后,rails将重定向到referer域,ruby-on-rails,devise,Ruby On Rails,Devise,我的本地机器上有两个rails应用程序,应用程序A和应用程序B。应用程序A使用登录令牌将访问者重定向到应用程序B,该令牌以前是从应用程序A(简单令牌\身份验证)收到的。URL看起来像是“/offers/F6MyubLfP5dKcrGLp?project_id=337&user_id=93&user_token=6s3xaoxRLNyJ8VG7wqEF”。在大多数情况下,它运行良好。身份验证成功,用户在应用程序B中看到正确的页面 但有时用户会被重定向到应用程序A。我不知道为什么以及从哪里开始调试

我的本地机器上有两个rails应用程序,应用程序A和应用程序B。应用程序A使用登录令牌将访问者重定向到应用程序B,该令牌以前是从应用程序A(简单令牌\身份验证)收到的。URL看起来像是
“/offers/F6MyubLfP5dKcrGLp?project_id=337&user_id=93&user_token=6s3xaoxRLNyJ8VG7wqEF”
。在大多数情况下,它运行良好。身份验证成功,用户在应用程序B中看到正确的页面

但有时用户会被重定向到应用程序A。我不知道为什么以及从哪里开始调试

当收到登录url并重定向(找到302)回应用A时,应用B的日志:

Started GET "/offers/F6MyubLfP5dKcrGLp?project_id=337&user_id=93&user_token=6s3xaoxRLNyJ8VG7wqEF" for ::1 at 2020-10-07 10:53:40 +0200
Processing by OffersController#show as HTML
  Parameters: {"project_id"=>"337", "user_id"=>"93", "user_token"=>"6s3xaoxRLNyJ8VG7wqEF", "id"=>"F6MyubLfP5dKcrGLp"}
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 92], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:58:in `require_login'
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 93], ["LIMIT", 1]]
   (0.3ms)  BEGIN
  ↳ app/controllers/application_controller.rb:65:in `after_successful_token_authentication'
  User Exists? (0.5ms)  SELECT 1 AS one FROM "users" WHERE "users"."wegateam_contact_id" = $1 AND "users"."id" != $2 LIMIT $3  [["wegateam_contact_id", 233], ["id", 92], ["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:65:in `after_successful_token_authentication'
   (0.6ms)  SELECT COUNT(*) FROM "users" WHERE "users"."authentication_token" = $1  [["authentication_token", "vDQWLATe_x5_V3AxL7ep"]]
  ↳ app/controllers/application_controller.rb:65:in `after_successful_token_authentication'
  User Update (0.6ms)  UPDATE "users" SET "authentication_token" = $1, "updated_at" = $2 WHERE "users"."id" = $3  [["authentication_token", "vDQWLATe_x5_V3AxL7ep"], ["updated_at", "2020-10-07 08:53:40.483669"], ["id", 92]]
  ↳ app/controllers/application_controller.rb:65:in `after_successful_token_authentication'
   (0.4ms)  COMMIT
  ↳ app/controllers/application_controller.rb:65:in `after_successful_token_authentication'
Redirected to http://localhost:5000/
Completed 302 Found in 98ms (ActiveRecord: 3.1ms | Allocations: 10039)
身份验证似乎是成功的,因为在执行了成功的\u-token\u身份验证后,简单的\u-token\u身份验证方法

# overwrite simple_token_authentication hook: token will only be valid for one login
  def after_successful_token_authentication
    current_user.update(authentication_token: nil)
    # Token will renewed when saving
  end
当它按预期工作时,http响应如下所示:

当执行未解除重定向时,如下所示:

当我在取消重定向后手动复制并粘贴url时,登录工作正常

似乎只有在不久之前创建了appb用户时,才会出现问题

我尝试的是:

  • 由于应用程序B的用户是在不久之前创建的(并将身份验证令牌发送给应用程序A),我认为Desive和simple_token_身份验证可能还没有准备好,这会导致重定向。因此,在应用程序a将用户发送到应用程序B的登录URL之前,我在应用程序a中超时了10秒。但结果相同
我甚至希望得到一些建议,我可以从哪里开始寻找这个问题的解决方案

更新:应用程序\u控制器

class ApplicationController < ActionController::Base
  before_action :store_user_location!, if: :storable_location?
  before_action :require_login

  include Pundit

  # Pundit: Ensure, that authorize has been called
  # after_action :verify_authorized
  # after_action :verify_policy_scoped

  # Catch Pundit::NotAuthorizedError
  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  # Prevent CSRF attacks by raising an exception.
  protect_from_forgery with: :exception, prepend: true

  # For simple_token_authentication (Bei Anforderung magic login kann der user nicht eingeloggt sein. In diesem Fall nicht
  # authentifizieren)
  acts_as_token_authentication_handler_for User, except: :request_magic_login

  def user_not_authorized
    flash[:error] = "Du hast keine ausreichende Berechtigung diese Seite zu öffnen."
    redirect_to(request.referrer || root_path)
  end

  # Devise Methode überschreiben, um nach Login zu der Seite weiterzuleiten, die der User egentlich aufrufen wollte,
  # bevor er auf die Login Seite geleitet wurde.
  def after_sign_in_path_for(resource_or_scope)
    stored_location_for(resource_or_scope) || super
  end

  private

  def redirect_to_project_or_select_page(user)
    if user.contact.projects.size != 1
      redirect_to user_projects_path(user)
    else
      redirect_to project_path(user.contact.projects.first.id)
    end
  end

  # Its important that the location is NOT stored if:
  # - The request method is not GET (non idempotent)
  # - The request is handled by a Devise controller such as Devise::SessionsController as that could cause an
  #    infinite redirect loop.
  # - The request is an Ajax request as this can lead to very unexpected behaviour.
  # https://github.com/heartcombo/devise/wiki/How-To:-Redirect-back-to-current-page-after-sign-in,-sign-out,-sign-up,-update
  def storable_location?
    request.get? && is_navigational_format? && !devise_controller? && !request.xhr?
  end

  def store_user_location!
    # :user is the scope we are authenticating
    store_location_for(:user, request.fullpath)
  end

  def require_login
    if !current_user && !devise_controller? && (!request.params[:user_id] || !request.params[:user_token])
      redirect_to new_user_session_path
    end
  end

  # simple_token_authentication hook überschreiben: token soll nur für einen Login gelten
  def after_successful_token_authentication
    current_user.update(authentication_token: nil)
    # Wird beim speichern dann neu gesetzt
  end
end
class ApplicationController
您正在执行多个查询以查找同一用户。这些可能会得到优化,但我认为问题也存在于某些地方。您能分享每个用户查询的用途吗?@TomDunning:第一个“用户加载”由应用程序\u控制器中的“require\u login”初始化。如果用户必须登录,它会检查大多数页面。如果需要,它会重定向到登录页面。接下来对用户的三个操作来自这一行:
current\u user.update(authentication\u token:nil)
simple\u token\u authentication
中,在\u token\u authentication成功后
。它确保用户在使用旧登录令牌时成为新登录令牌。我现在不明白为什么这一行会导致三个DB操作。@TomDunning:我忘了说,当url(!request.params[:user_token])中存在令牌时,require_login不会重定向到登录页面,所以您使用的是这个标准钩子:。是否已检查是否允许所有可能发送此请求的服务器?如果这是一个随机错误,那么可能是CSRF令牌没有为您的一台服务器排队。如果不是这样,我需要看更多的代码。理想情况下,应用程序\u控制器和您发送的回退选项。我还将检查当前_用户的设置位置,并确保不存在清除该令牌突然使其无效的竞争条件。最后,我想知道他们在成功后会进入哪一页。@TomDunning所有允许的服务器?我想是的,因为当我第二次尝试与该用户相同的设置时,它是有效的(除此之外,两个应用的服务器都是相同的,localhost)。CSRF令牌没有排队?我不这么认为,因为在应用程序中,controller
用::exception保护\u不被伪造,prepend:true