![](/img/trans.png)
[英]How can I set the authentications table when using Omniauth Identity?
[英]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,則可以忽略提供商列。 您也可以根據需要命名模型OathAccount
或InstagramAccount
或任何喜歡的名稱。
我們可以生成身份驗證模型:
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.