2015-05-19 66 views
0

我需要允許用戶使用3個Instagram帳戶進行身份驗證。我正在開發Ruby On Rails,並使用Instagram OAuth如何使用OmniAuth爲每個用戶允許多個Instagram驗證?

在我的Devise配置中,我添加了config.omniauth :instagram, ENV['INSTAGRAM_client'], ENV['INSTAGRAM_secret'], {:scope => 'basic'}。這僅用於一次認證。我的問題是如何設置兩個不同的帳戶進行身份驗證,以便我可以分別處理它們與這個寶石,以及如何訪問它們?

+0

有您創建一個單獨的模型來存儲認證? – max

+0

@papirtiger不,你能指導我怎麼做?我會接受你的回答。我需要從一個用戶的三個Instagram應用獲取信息 –

+0

@AigarsCibuļskis請不要污衊您的問題。 –

回答

1

創建多認證(或多供應商)應用程序的第一步是將您的用戶模型與認證分開。

請確保您在開始之前閱讀https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

我們要像下面這樣:

class User < ActiveRecord::Base 
    has_many :authentications 
end 

# Represents an OAuth authentication account 
class Authentication < ActiveRecord::Base 
    belongs_to :user 
    alidates_uniqueness_of :uid, scope: :provider 
end 

這是基於一個多供應商設置 - 如果你只打算使用的Instagram,你可以省略提供商列。您也可以根據需要命名模型 - OathAccountInstagramAccount或任何您喜歡的。

我們可以生成認證模式:

rails g authentication uid:string provider:string user:references 

我們也想增加一個數據庫索引加快查詢速度,並確保我們只有每個Twitter賬戶一個認證。因此,讓我們編輯的遷移:

class CreateAuthentications < ActiveRecord::Migration 
    def change 
    create_table :authentications do |t| 
     # ... 
    end 
    # add this line 
    add_index :authentications, [:provider, :uid], unique: true 
    end 
end 

現在,我們需要處理OAuth回調 - 這是供應商對話框,他們選擇批准或拒絕該應用程序後顯示。讓我們建立一個路線:在用戶登錄後

devise_for :users, skip: [:sessions], controllers: { 
    omniauth_callbacks: 'users/omniauth_callbacks' 
} 

所以,現在將被路由到/users/omniauth_callbacks/twitter

然後,我們創建一個控制器:

# app/controllers/users/omniauth_callbacks_controller.rb 
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 
    def instagram 
    # OmniAuth creates a normalized 
    # hash of the credentials and info supplied by the provider. 
    @auth_params = request.env["omniauth.auth"] 
    # @todo check if authentication exists 
    # @todo find user for authentication 
    # @todo create account for new users 
    # @todo sign user in 
    end 
end 

爲了處理這一切的邏輯,我們可能要在服務對象調用。這些只是簡單的 接受輸入並完成任務的紅寶石對象。

# app/services/authenticate_service 
class AuthenticateService  
    # @param [Hash|OmniAuth::AuthHash] auth_hash 
    # @param [User|nil] current_user 
    # @return [Authentication] 
    def call(auth_hash, current_user = nil) 
    auth = Authentication.find_or_initialize_by(uid: auth_hash[:uid], provider: auth_hash[:provider]) 
    if !current_user || !auth.user 
     # You need to adapt this to the provider and your user model 
     user = User.new(
     name: auth_hash[:info][:full_name] 
    ) 
    end 
    auth.update(user: current_user ? current_user : user) 
    end 
end 

這使得它比測試我們的控制器中的所有邏輯容易得多。 我們可以只注入任何散列並使用我們想要的用戶對象。

只是一個小小的警告 - 我們需要告訴導軌自動載入我們的服務

# config/application.rb 
config.autoload_paths += Dir[Rails.root.join('app', 'services', '{**}')] 

現在讓我們撥打我們的服務,並推薦閱讀登錄用戶在

# app/controllers/users/omniauth_callbacks_controller.rb 
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController 
    def instagram 
    @auth = AuthenticateService.new.call(request.env['omniauth.auth'], current_user) 
    @user = @auth.user 
    if user_signed_in?  
     flash[:notice] = 'You have added a new authentication!' 
     redirect_to :root 
    else 
     sign_in_and_redirect(:user, @user) 
    end 
    end 
end 

+0

這是一個非常高級的話題,您需要了解Rails和OAuth如何工作的基本知識。如果您剛剛開始使用導軌,我不會支持您。 – max

+0

編輯:刪除了一條線路故障線路,即使沒有線路,也會嘗試將認證分配給當前用戶。 – max

相關問題