簡體   English   中英

如何使用OmniAuth允許每個用戶幾個Instagram身份驗證?

[英]How do I allow several Instagram authentications per user with OmniAuth?

我需要允許用戶使用3個Instagram帳戶進行身份驗證。 我正在Ruby On Rails上進行開發,並且正在使用Instagram OAuth

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

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

在開始之前,請確保您已閱讀https://github.com/plataformatec/devise/wiki/OmniAuth:-概述。

我們想要以下內容:

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后,將會被路由到/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

這比我們在控制器中擁有所有邏輯要容易得多。 我們可以注入任何哈希值並使用所需的用戶對象。

僅需注意一點-我們需要告訴Rails自動加載我們的服務

# 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

建議閱讀:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM