Rails,Devise 无法使用 cURL 退出。

Rails, Devise can not use cURL to signout.

我正在关注 this tutorial to create user authentication with devise from Android. However, Devise remove :token_authenticable hence, I am using what they refer in this gist。但是,我 运行 遇到了一些我不知道如何解决的问题。

这是代码。

在用户模型中。

before_save :ensure_authentication_token

devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :trackable, :validatable,
    :confirmable

def ensure_authentication_token
    if authentication_token.blank?
        self.authentication_token = generate_authentication_token
    end
end

def skip_confirmation!
    self.confirmed_at = Time.now
end

private
    def generate_authentication_token
        loop do
            token = Devise.friendly_token
            break token unless User.where(authentication_token: token).first
        end
    end

在应用程序控制器中:

protect_from_forgery with: :exception
before_filter :authenticate_user_from_token!

private
    # For this example, we are simply using token authentication
    # via parameters. However, anyone could use Rails's token
    # authentication features to get the token from a header.
    def authenticate_user_from_token!
        user_token = params[:user_token].presence
        user = user_token && User.find_by_authentication_token(user_token.to_s)

        if user
            # Notice we are passing store false, so the user is not
            # actually stored in the session and a token is needed
            # for every request. If you want the token to work as a
            # sign in token, you can simply remove store: false.
            sign_in user, store: false
        end 
    end 

在会话控制器中API

class Api::SessionsController < Devise::SessionsController
 skip_before_filter :verify_authenticity_token,
                 :if => Proc.new { |c| c.request.format == 'application/json' }
 before_action :authenticate_user_from_token!, only: [:create]
 respond_to :json
 def create
     warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
     render :status => 200,
     :json => { :success => true,
     :info => t("devise.sessions.signed_in"),
     :data => { :auth_token => current_user.authentication_token } }
 end

 def destroy
    warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
    current_user.update_column(:authentication_token, nil)
    render :status => 200,
    :json => { :success => true,
    :info => t("devise.sessions.signed_out"),
    :data => {} }
 end

结束

当我执行curl登录时:

curl -v -H 'Content-Type: appl-H 'Accept: application/json' -X POST http://localhost:3000/api/sessions -d "{\"user\":{\"email\":\"[FILTERED]\",\"password\":\"123123123\"}}"

这是来自服务器的日志:

Started POST "/api/sessions" for 127.0.0.1 at 2015-01-23 13:47:05 +1300
Processing by Api::SessionsController#create as JSON
Parameters: {"user"=>{"email"=>"[FILTERED]", "password"=>"[FILTERED]"}, "session"=>{"user"=>{"email"=>"[FILTERED]", "password"=>"[FILTERED]"}}}
User Load (0.1ms)  SELECT  "users".* FROM "users"  WHERE "users"."email" = '[FILTERED]'  ORDER BY "users"."id" ASC LIMIT 1
(0.1ms)  begin transaction
SQL (0.2ms)  UPDATE "users" SET "current_sign_in_at" = ?, "last_sign_in_at" = ?, "sign_in_count" = ?, "updated_at" = ? WHERE "users"."id" = 1  [["current_sign_in_at", "2015-01-23 00:47:05.981119"], ["last_sign_in_at", "2015-01-23 00:28:49.300907"], ["sign_in_count", 3], ["updated_at", "2015-01-23 00:47:05.981736"]]
(103.8ms)  commit transaction
Completed 200 OK in 185ms (Views: 0.4ms | ActiveRecord: 104.9ms)

当我执行 curl 以注销时:

curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X DELETE http://localhost:3000/api/sessions/?auth_token=TbQXZJtngfJqZK6HkHKF

这是服务器日志:

Started DELETE "/api/sessions/?auth_token=TbQXZJtngfJqZK6HkHKF" for 127.0.0.1 at 2015-01-23 13:50:22 +1300
Processing by Api::SessionsController#destroy as JSON
Parameters: {"auth_token"=>"TbQXZJtngfJqZK6HkHKF", "session"=>{}}
Filter chain halted as :verify_signed_out_user rendered or redirected
Completed 204 No Content in 1ms (ActiveRecord: 0.0ms)

当我在 SessionController API 中添加 skip_filter:verify_signed_out_user, only:[:destroy] 时,服务器日志将是:

Started DELETE "/api/sessions/?auth_token=TbQXZJtngfJqZK6HkHKF" for  127.0.0.1 at 2015-01-23 13:58:55 +1300
Processing by Api::SessionsController#destroy as JSON
Parameters: {"auth_token"=>"TbQXZJtngfJqZK6HkHKF", "session"=>{}}
Completed 401 Unauthorized in 1ms

我不明白为什么 returns 204 没有内容.... 如果有人知道发生了什么。我们将不胜感激。 干杯。

成功销毁资源的 HTTP 状态为 204。查看 http://httpstatus.es/204 了解更多信息。

当您跳过过滤器时,它会返回 401,即未授权访问资源的 HTTP 状态。这是正确的,因为您在销毁结果之前要求进行身份验证。

一切似乎都是正确的,我看不出问题。