2

我有一个使用设计登录的应用程序。我在 Web 应用程序中有一个登录表单,用于对数据库的用户进行身份验证,并简单地将 @user 哈希作为 json 字符串返回。

目标是让用户对用户进行身份验证并检索他们的 authentication_token 以供将来在应用程序中使用,以防止用户必须不断登录。

问题是我无法将 authentication_token 包含在返回的 json 中。

我的 user.rb 模型

attr_accessible :authentication_token, :email, :password, :password_confirmation, :remember_me,  :bio, :confirmed, :deposit, :email, :fri25, :mon21, :name, :paid, :picture, :sat26, :sun20, :sun27, :thur24, :tue22, :wed23

清楚地包括 authentication_token 符号。

然后在会话控制器中,我有一个名为 newApi 的自定义操作,它运行一个简单的身份验证方法并以 @user 哈希作为 json 响应。

def newapi
 @user = User.authenticate(params[:email],params[:password])
 respond_to do |format|
   format.json { render json: @user }
 end

结束

然而,无论我做什么,身份验证令牌都不包含在 json 响应中。我错过了一些明显的东西吗?为什么不包括在内?

4

5 回答 5

4

Devise > 2.x 似乎从 xml 和 json 响应中去除了属性。这可能是一项安全功能,但我不确定它是从哪里引入的。“受保护的属性”列表在这里:

https://github.com/plataformatec/devise/blob/master/lib/devise/models/authenticatable.rb

第 54 行:

BLACKLIST_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
    :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
    :last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
    :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at, :authentication_token]

初始化它的代码在第 122-135 行

评论说您可以提供自己的黑名单属性列表,或分别使用:force_except和附加到现有列表。:except

我的 hacky 解决方案是这样的:

def newapi
  @user = User.authenticate(params[:email],params[:password])
  respond_to do |format|
    format.json { render json: @user.as_json(:force_except => Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION.delete_if{|x| x == :authentication_token} }
  end
end

但我认为有一种方法可以在更优雅的地方覆盖这个列表,比如在初始化程序中。我的作品,但可能不是最好的答案。

于 2012-06-15T05:58:54.307 回答
3

虽然这很旧,但我所做的只是使用它的“方法”选项

to_json(methods: :arbitrary_method)

因为从技术上讲,所有属性都成为模型上的可访问方法。这似乎最轻松:D

在此页面上: http: //api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html

于 2016-02-17T19:07:14.693 回答
1

我的解决方法:

class User < ActiveRecord::Base
  # include devise token_authenticatable and others
  devise  :token_authenticatable

  # after devise finds our user (such as when logging in)
  after_find :write_auth_token

  # write our pseudo attribute to the model
  def write_auth_token
    write_attribute(:auth_token, self.authentication_token)
  end

  # make our pseudo attribute attr_accessible
  attr_accessible :auth_token
end
于 2012-07-25T16:22:27.283 回答
0

我最终通过使用jbuilder自己解决了这个问题。

本质上,您只需删除render json: @user调用并使用 jbuilder 模板。

在 newapi.json.jbuilder 中

json.(
  @user, 
  :authentication_token, 
  :email, 
  :password, 
  :password_confirmation, 
  :remember_me,
  :bio, 
  :confirmed, 
  :deposit, 
  :email, 
  :fri25, 
  :mon21, 
  :name, 
  :paid, 
  :picture, 
  :sat26, 
  :sun20, 
  :sun27, 
  :thur24, 
  :tue22, 
  :wed23
)

如果您有这条路线,请查看他们的文档,因为它可以满足我的所有需求,而且是我们现在返回 api 的唯一方法。如果您之前没有使用过它,请检查一下!它使 API 端点非常简单。

如果您想推出自己的设置,Nick Knudson 的回答也是有效的。

于 2012-08-01T16:02:40.610 回答
0

@Travis Todd 的回答完全可以,是的,可能有一个更优雅的解决方案。此外,如果您想为数据库迁移或其他类似目的构建私有或临时 api,而您需要 2 个或更多这些黑名单属性,您可能需要执行以下操作:

def newapi
  @devise_attrs = [:encrypted_password, :remember_created_at, :sign_in_count, :current_sign_in_at] #etc..
  @user = User.authenticate(params[:email],params[:password]).includes(:identity)
  respond_to do |format|
    # I added a few other options and updated ruby syntax so that you can see how can this be customized if in need of specific user attributes or relations.
    format.json { render json: @user.as_json(force_except: Devise::Models::Authenticatable::BLACKLIST_FOR_SERIALIZATION.delete_if{|x| @devise_attrs.include?(x)}, include: [:identity]), status: 200 }
  end
end

仍在等待另一个舔手指的优雅解决方案。

于 2016-02-18T16:27:12.827 回答