Rails JSON API 的简单令牌认证注销

Posted

技术标签:

【中文标题】Rails JSON API 的简单令牌认证注销【英文标题】:Simple Token Authentication Signout for Rails JSON API 【发布时间】:2015-03-04 10:56:28 【问题描述】:

我有一个 Rails 应用程序(主要是 JSON API) 我正在使用Devise 使用来自任何来源(网络、移动)的 JSON 请求进行身份验证 我正在使用Simple Token Authentication 使用 HTTP 标头对用户进行身份验证。

我不确定实现应该是什么样子,但我已经起草了一个几乎可以工作的实现。

只有一个问题。那就是当用户尝试注销时...通常它应该使用户的身份验证令牌无效...但事实并非如此,我不确定问题出在哪里...无论是与设计还是Simple Token Auth...所以任何帮助都非常感谢。

但这里是代码

  # router
  devise_for :users, controllers:  sessions: 'sessions',
                                    registrations: 'registrations' 
  api vendor_string: 'app', default_version: 1, path: '', format: 'json' do
    version 1 do
      cache as: 'v1' do
        resource :some_resource
      end
    end

会话控制器是这样的

class SessionsController < Devise::SessionsController  
  respond_to :json
  skip_filter :verify_signed_out_user, only: :destroy

  def create
    self.resource = warden.authenticate!(scope: resource_name)
    render :create, status: :created
  end

  def destroy
    current_user.authentication_token = nil
    # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ take note of this line
    current_user.save!
    super
  end
end  

前面提到的行似乎有问题...当用户提供错误的令牌标头时,它仍在工作,当前用户指的是不应该首先进行身份验证的用户..例如这里是 2 个电话,规格

describe 'DELETE sessions#destroy' do
    let(:user)  Fabricate(:confirmed_user) 
    let(:auth_token)  user.authentication_token 
    describe 'with request headers' do
      context 'valid credentials' do
        it 'Returns 204' do
          delete '/users/sign_out', , 
            HTTP_CONTENT_TYPE: 'application/json',
            HTTP_ACCEPT: "application/vnd.app+json; version=1",
            "X-User-Email" => user.email,
            "X-User-Token" => user.authentication_token
          

          user.reload
          expect(response.status).to eq 204
          expect(user.authentication_token).not_to eq auth_token
          #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is ok cause it's the valid user
        end
      end

      context 'invalid credentials' do
        it 'Returns 204' do
          delete '/users/sign_out', , 
            HTTP_CONTENT_TYPE: 'application/json',
            HTTP_ACCEPT: "application/vnd.app+json; version=1",
            "X-User-Email" => user.email,
            "X-User-Token" => 'Invalid'
          

          user.reload
          expect(response.status).to eq 204
          expect(user.authentication_token).to eq auth_token
          #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this FAILS
          # why did the user get new auth token when didn't sign out ????
        end
      end
    end

Github 上也有报道

为了完整起见,这里是应用程序控制器

class ApplicationController < ActionController::Base
  # The API responds only to JSON
  respond_to :json

  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  # default to protect_from_forgery with: :exception
  protect_from_forgery with: :null_session

  # Token Authenticatable for API
  acts_as_token_authentication_handler_for User
end

【问题讨论】:

【参考方案1】:

来自 github 上的 simple_authentication_token page,如果每次保存 current_user 时 current_user.authentication_token 为空白 (nil),则会自动生成。

假设user是User的一个实例,它是token可认证的:每次user都会被保存,而user.authentication_token.blank?它会收到一个新的唯一身份验证令牌(通过 Devise.friendly_token)。

更新

在您的sessions_controller.rb 中添加acts_as_token_authentication_handler_for User

【讨论】:

是的,我知道,但测试表明它不起作用......这也不是我第一个使用简单身份验证令牌的项目......我可以向你保证,这个问题存在于所有其中【参考方案2】:

请继续阅读https://github.com/gonzalo-bulnes/simple_token_authentication/issues/224。我认为这是正常的行为。您需要删除客户端(设备)上的令牌

【讨论】:

以上是关于Rails JSON API 的简单令牌认证注销的主要内容,如果未能解决你的问题,请参考以下文章

无法解释无效的 CSRF 令牌 rails api

Rails Set-Cookie on json API 响应

django-rest-framework 令牌认证和注销

使用 Rails 和 HTTParty 将 JSON 发布到 API

利用Redis撤销JSON Web Token产生的令牌

使用 Devise 从 Rails 上的 json api 进行身份验证