使用{render json:}时缺少的属性

时间:2012-04-22 04:54:16

标签: ruby-on-rails json devise render

我有一个使用设计登录的应用程序。我在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

eend

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

5 个答案:

答案 0 :(得分:4)

设计> 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

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

答案 1 :(得分:3)

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

to_json(methods: :arbitrary_method)

因为所有属性在技术上都成为模型上的可访问方法。这似乎最无忧无虑:D

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

答案 2 :(得分: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

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:-1)

我最终使用jbuilder解决了问题。

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

in 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的回答也是有效的。