【问题标题】:How to use the `authenticate_or_request_with_http_token` method如何使用 `authenticate_or_request_with_http_token` 方法
【发布时间】:2016-01-24 11:59:10
【问题描述】:

我正在向我的仅 Rails API 应用程序添加一些身份验证,就像在我的 application_controller.rb 中一样:

def is_admin
  authenticate_or_request_with_http_token do |token, options|
    if User.find_by(:auth_token => token)
      value = true
    else 
      value = false
    end
  end
end

在我的控制器中:

admin = is_admin
if admin
  @voices = Voice.all.map do |voice| 
    voice.format
  end
else
  @voices = 'Something else'
end

当我登录时,一切正常,但是当我没有登录时,我收到以下错误:Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".

虽然没有登录,但我期待收到“其他”响应,然后我会继续进行相应的处理。

任何想法为什么会发生这种情况?

【问题讨论】:

  • 好吧 value 甚至没有被使用。您可以只用User.exists?(auth_token: token) 替换authenticate_or_request_with_http_token 方法的主体。至于您的其他问题 - 检查 rails 日志 (tail -f logs/development.log),它会向您显示第一次调用 render 的位置。
  • 我已经更改了authenticate_or_request_with_http_token 中的块,并且按照您的建议正常工作。问题是我在development.log 上找不到第一个渲染调用。每次被调用时,它似乎都来自我的控制器(我正在处理的那个),并且只有在我使用authenticate_or_request_with_http_token 时才会发生。假设我手动设置了admin = false 的值而不是admin = is_admin 我没有收到错误。
  • 老实说,我正在寻找的只是一种识别请求是否被授权的方法。然后相应地修改响应。您对我如何做到这一点有什么建议吗?

标签: ruby-on-rails authentication


【解决方案1】:

authenticate_or_request_with_http_token 用于在操作之前运行的before_action 过滤器中。或显式返回。

如果您只是想检查用户是否存在,您可以使用不发送响应的authenticate_with_http_token

# app/helpers/authorization_helper.rb
module AuthorizationHelper
  # returns true/false
  # sets @current_user if the request is authenticated 
  def authenticate!
    return true if @current_user  # avoid re-querying the DB
    authenticate_with_http_token do |token, options|
      @current_user = User.find_by(:auth_token => token)
    end
  end

  def is_admin?
    authenticate!
  end
end

# app/controllers/api_controller.rb
# or whatever controller you use as a base
class ApplicationController < ActionController::API
  include AuthorizationHelper
end

# in your controller
def index
  if is_admin?
    @voices = Voice.all.map do |voice| 
    voice.format
  else
    @voices = 'Something else'
  end
end

【讨论】:

  • 这正是我想要的。谢谢!
【解决方案2】:

您也可以这样做,或者更确切地说是 max 答案的一个选项。

# app/controllers/application_controller.rb
class ApplicationController
  def authorization!
    authenticate_with_http_token do |token, options|
      @current_user = User.find_by(:auth_token => token)
    end

    unless @user.present?
      # You could return anything you want if the response if it's unauthorized. in this
      # case I'll just return a json object 
      return render json: {
        status: 300,
        message: "Unauthorized access in the API"
      }, status: 401
    end
  end
end

# in your controller just add a before_action method
before_action :authorization

def index
  @voices = Voice.all.map do |voice| 
  voice.format
end

在这种情况下,您不需要在每个需要身份验证的请求中添加 if 语句。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-07
    • 2013-09-19
    • 2012-03-10
    • 2012-08-31
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多