自定义 Devise 的 401 未授权响应

23

我正在为我的Rails 3.1应用程序开发基于JSON的API。我想提供一个自定义的错误响应,而不是默认的响应:

{"error":"You need to sign in or sign up before continuing."}

我的API控制器包含一个before_filter调用 authenticate_user!,这就是渲染这个JSON响应的原因。

在搜索过程中,我发现了这个StackOverflow问题,它引用了这篇Devise维基页面。不幸的是,这篇维基页面对我来说不够详细,我不知道它告诉我该怎么做。具体来说,我不知道我应该把那段代码放在哪里,这样Devise/Warden就知道要呈现我想要的东西了。

从其他SA问题的评论中可以看出,由于我使用的Devise版本高于1.2(具体为1.4.2),因此似乎不需要调用custom_failure!。然而,这篇维基页面并没有解释render调用应该放在哪里,以便authenticate_user!知道使用它而不是自己的渲染调用。

这个render调用放在哪里?

编辑:我不仅想改变消息本身(就像设备en.yml配置那样);我想改变响应的实际格式。具体来说,我想返回这个:

render :text => "You must be logged in to do that.", :status => :unauthorized

你成功了吗?如果是的话,我将覆盖SessionController#create方法,但我不知道在哪里放置这个format.json { render :json => { "status" => ERROR_NOT_REGISTERED }, :status => :unauthorized } - Mateusz
2个回答

32

如果有其他人在寻找如何自定义 Devise 的登录失败 JSON 错误响应时,请参考此问题的答案。关键是使用自己定制的 FailureApp 实现。(您还可以使用此方法来覆盖一些重定向行为。)

class CustomFailureApp < Devise::FailureApp
  def respond
    if request.format == :json
      json_error_response
    else
      super
    end
  end

  def json_error_response
    self.status = 401
    self.content_type = "application/json"
    self.response_body = [ { message: i18n_message } ].to_json
  end
end

在您的devise.rb文件中,查找config.warden部分:

  config.warden do |manager|
    manager.failure_app = CustomFailureApp
  end

一些相关信息:

起初我认为我需要覆盖Devise::SessionsController,可能会使用传递给warden.authenticate!recall选项,但正如这里所述,“回调不会被用于API请求,只用于导航请求。如果您想自定义HTTP状态码,则最好在失败应用程序级别进行设置。”

此外,https://github.com/plataformatec/devise/wiki/How-To%3a-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated展示了与重定向非常相似的内容。


我不再有这个问题了,但根据我的问题所收到的投票数,你的回答显然会对很多人有帮助。感谢分享! - Matt Huggins
是的,我希望这能为其他人节省一些时间。 :) - qix
谢谢您。确实为我节省了很多时间。 - Doug
1
@vonspotz Devise的维基还提到:"如果您遇到未初始化常量CustomFailure错误,并且将CustomFailure类放在/lib目录下,请确保在您的application.rb文件中自动加载lib文件,如下:config.autoload_paths << Rails.root.join('lib')" - qix
@qix 谢谢,我已经将该路径放入我的autoload_path中,但是没有更多关于FailureApp的文档,也不知道如何使用它。似乎你只能重写方法,而且我甚至无法在我的子类和重写的方法中调用redirect_to。所以现在我正在尝试使用Identity gem和其他身份验证方法进行OAuth。这似乎更加灵活。 - von spotz
显示剩余2条评论

2
如果您只想更改错误消息显示的文本,我认为您可以编辑语言环境文件(/config/locales/devise.en.yml)。
如果您想了解更具体的细节,这个主题的RailsCast也可能会有帮助。 您可以在http://railscasts.com/episodes/210-customizing-devise找到它。

谢谢指出。到目前为止,我一直在我的项目中使用自定义错误响应来处理该语言环境文件,但实际上我正在寻求更改响应格式的解决方案。我已经更新了问题以包括这一点。 - Matt Huggins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接