我有一个使用设计登录的应用程序。我在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响应都不包含身份验证令牌。我错过了一些明显的东西吗为什么不包括在内?
答案 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模板。
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的回答也是有效的。