【问题标题】:How to use Devise for authentication when using an API使用 API 时如何使用 Devise 进行身份验证
【发布时间】:2018-08-01 04:16:55
【问题描述】:

我知道还有其他类似的问题,但在我的情况下没有一个答案有效。我正在尝试通过 API 对用户进行身份验证。更具体地说,我有一个 iPhone 应用程序充当“客户端”,它将发布请求发送到我拥有的会话控制器。这里是:

class V1::SessionsController < ApplicationController

  def create
    @user = User.find_by_username(params[:username])

    if @user
      if @user.valid_password?(params[:password])
        sign_in(@user)
        render :create
      else 
        render_error_for @user
      end
    else
      render json: {
        status: 'ERROR',
        data: ['Incorrect Username']
      }, status: :unauthorized
    end
  end 
end

我在网上看到sign_in(@user) 应该让用户登录,但这并没有按预期工作。此外,我读到您应该在登录之前重新加载用户,如下所示:@user.reload。这也不起作用。我想知道这是否与我没有从Devise::SessionsController 继承的事实有关。我学会了如何在线制作这样的会话控制器,所以这可能是问题所在。

我测试的方法是在 rails 控制台中运行user.last_sign_in_at,但我得到的只是nil,我很确定这意味着设计没有成功登录用户.任何帮助表示赞赏,谢谢。

更新

def create
    @user = User.find_by_username(params[:username])

    if @user
      if @user.valid_password?(params[:password])
        @user.last_sign_in_at = Time.now
        render :create
      else 
        render_error_for @user
      end
    else
      render json: {
        status: 'ERROR',
        data: ['Incorrect Username']
      }, status: :unauthorized
    end
  end

我找到了一个可能的解决方案,但我没有将其标记为解决方案,因为在我看来这个解决方案并不安全。我实质上是用我自己的流程来创建会话(并将 DateTime 分配给 last_sign_in_at 字段)来代替 Devise 的流程。这安全吗?或者这样做是个坏主意?硬编码 Devise 的 sessions#create 操作由于某种原因不起作用。我推测这与这是一个 API 而不仅仅是一个常规网站这一事实有关。

【问题讨论】:

  • 根据我的建议,请选择gem doorkeeper

标签: ruby-on-rails api devise


【解决方案1】:

正如你所说的More specifically, I have an iPhone app acting as the "client" and it sends posts requests to a sessions controller I have

所以我可能认为您需要的响应将包括用户信息和身份验证令牌。

试试这个方法:

class SessionsController < Devise::SessionsController

  skip_before_action :verify_authenticity_token # skip CSRF check for APIs
  respond_to :json

  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message!(:notice, :signed_in)
    sign_in(resource_name, resource)
    yield resource if block_given?
    respond_with(resource)
 end

 def respond_with(resource, opts = {})
   render json: resource.as_json(only: [:id,:email, :name, ... ])
                      .merge!({token: resource.token})
 end
end

问候令牌,您可以检查 :jwt_authenticatable, :jwt_revocation_strategy 在设计宝石中。

因此响应将具有用户和令牌:用户将是用户信息,令牌是该用户的身份验证令牌。 然后,您需要在下次调用另一个请求到后端时存储该令牌,确保将其作为授权包含在标头中。

在后端,我们根据身份验证令牌获取当前用户。

【讨论】:

  • 当我尝试从 Devise::SessionsController 继承时,我收到一条错误消息:&lt;AbstractController::ActionNotFound: Could not find devise mapping for path /v1/sessions/ 我觉得这与我的路线有关。我会继续尝试调试。
  • 好的,我修复了路由,但self.resource = warden.authenticate!(auth_options) 总是失败。显然,因为这是一个 API,我也没有向用户发送 flash 错误的方法。
  • 该方法来自设计。
  • 在路由中,你应该有它:devise_for :users, controllers: { sessions: 'sessions' }
  • 是的,我有。路线现在运行良好;只是warden.authenticate!(auth_options) 总是失败。
【解决方案2】:

您可以试用device-token-auth gem,它建立在 API 身份验证的设计之上。

请查看documentation,其中描述了用法。

【讨论】:

  • 我去看看
猜你喜欢
  • 2014-01-04
  • 1970-01-01
  • 2012-07-20
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 2014-12-24
  • 2016-08-30
  • 2017-01-16
相关资源
最近更新 更多