2

ログインにdeviseを使用するアプリがあります。データベースに対してユーザーを認証し、@userハッシュをjson文字列として返すだけのログインフォームがWebアプリにあります。

目標は、ユーザーにユーザーを認証させ、アプリで将来使用するためにauthentication_tokenを取得して、ユーザーが継続的にログインする必要がないようにすることです。

問題は、返されるjsonにauthentication_tokenを含めることができないことです。

私の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応答に含まれていません。明らかな何かが欠けていますか?なぜ含まれていないのですか?

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

私のハッキーな解決策はこれです:

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の答えは完全に機能します。そうです、もっとエレガントな解決策があるかもしれません。さらに、db移行またはこれらのブラックリスト属性の2つ以上が必要な他の同様の目的のためにプライベートまたは一時的な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

このための別の指をなめるエレガントな解決策をまだ待っています。

于 2016-02-18T16:27:12.827 に答える