Rails 5 + OmniAuth + Devise 實作可擴充的第三方網站登入(Facebook, Google)
source link: https://blog.niclin.tw/2017/08/26/rails-5---omniauth---devise-%E5%AF%A6%E4%BD%9C%E5%8F%AF%E6%93%B4%E5%85%85%E7%9A%84%E7%AC%AC%E4%B8%89%E6%96%B9%E7%B6%B2%E7%AB%99%E7%99%BB%E5%85%A5facebook-google/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Rails 5 實作第三方登入 (Facebook + google)
雖然我去年寫過一篇如何在 Rails 4 Devise使用Google實作登入
但後來要用的時候,發現原本的文章只能對應一種第三方登入,如果要實作多個第三方登入在同一個網站的時候,可擴充性就顯得相當重要了。
再加上這種套件或是API接口的升級變化越來越快,還是寫一篇新的吧(應該不會每年都寫一篇啦XD)
Gem install
gem `devise`
gem 'omniauth'
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
gem 'koala' # 可以將錯誤的 session 刪掉避免註冊失敗
因為 devise 有支援第三方登入,所以實作起來並不特別難。
申請官方接口 Facebook
先去 Facebook 開發者官方註冊,如果已有帳號直接登入應該就行了。
然後右上角,下拉選單選擇「新增應用程式」
螢幕快照 2017-08-26 下午10.17.06.png
輸入你的 app name
螢幕快照 2017-08-26 下午10.18.29.png
接著會跳轉到這個 app 下的後台設定,點擊左邊 Side bar 去建立新平台
螢幕快照 2017-08-26 下午10.21.34.png
新建網站平台
螢幕快照 2017-08-26 下午10.23.37.png
輸入網址,這邊注意一下,如果你想要先在 localhost 測試,可以先填入 http://localhost:3000
,等到上去正式站或測試站在調整正確網址就行了,因為這個欄位是 Facebook 要確定打回去的 redirect url 是否跟設定一樣
螢幕快照 2017-08-26 下午10.24.14.png
最後 Deploy 上去要給別人測試的時候,記得到這裡把應用程式設定公開,否則只有開發者帳號能夠用 Facebook 的第三方登入哦
螢幕快照 2017-08-26 下午10.26.14.png
申請官方接口 Google
點下拉選單來新增一個應用程式的專案
螢幕快照 2017-08-26 下午10.29.38.png
點擊「+」符號
螢幕快照 2017-08-26 下午10.30.21.png
接著會讓你輸入這個專案的名稱,輸入完之後會跳回原本的畫面,在選一次下拉選單,應該就會看到他正在建立了,等待建立好(約十秒)就可以點進去
然後啟用 Web Fonts Developer API
and Google+ API
點擊新增 API 就會出現搜索欄可以找了,
找到之後點選啟用,接著會叫你建立憑證,憑證建立後就會拿到 api key 和密鑰
Controller 設定
新建 Users::OmniauthCallbacksController
指令 rails g controller users::omniauth_callbacks
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
@user = User.from_omniauth(request.env["omniauth.auth"], current_user)
if @user.persisted?
sign_in_and_redirect @user, :event => :authentication
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
if @user.email.nil?
@user.delete_access_token(request.env["omniauth.auth"])
redirect_to new_user_registration_url, alert: "需要您同意 Email 授權唷!"
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
def google_oauth2
@user = User.from_omniauth(request.env["omniauth.auth"], current_user)
if @user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
sign_in_and_redirect @user, :event => :authentication
else
session["devise.google_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to new_user_session_path, alert: "無法獲得驗證!"
end
end
建立一個紀錄第三方資料的 model
rails g model identity user:references provider:string uid:string
rake db:migrate
初始化 model
class Identity < ApplicationRecord
belongs_to :user
validates_presence_of :uid, :provider
validates_uniqueness_of :uid, :scope => :provider
def self.find_for_oauth(auth)
find_or_create_by(uid: auth.uid, provider: auth.provider)
end
end
驗證如果有相同 email 帳戶直接登入,沒有的話新建一個並登入,如果你有用驗證信請記得要 skip confirm
devise: :omniauthable, :omniauth_providers => [:facebook, :google_oauth2]
def self.from_omniauth(auth, signed_in_resource = nil)
identity = Identity.find_for_oauth(auth)
user = signed_in_resource ? signed_in_resource : identity.user
if user.nil?
email = auth.info.email
user = User.where(email: email).first if email
if user.nil?
user = User.new(name: auth.info.name.gsub(/\s+/, '_'),
email: auth.info.email,
avatar: auth.info.image,
password: Devise.friendly_token[0,20])
user.save!
end
end
if identity.user != user
identity.user = user
identity.save!
end
user
end
def delete_access_token(auth)
@graph ||= Koala::Facebook::API.new(auth.credentials.token)
@graph.delete_connections(auth.uid, "permissions")
end
devise 的 routes 用我們剛建立的 controller 覆蓋
devise_for :users, :controllers => { omniauth_callbacks: "users/omniauth_callbacks" }
將你拿到的第三方金鑰與密碼填在這裡,如果不想把密鑰寫在 commit 裡面,可以使用 dotenv 這個 gem 來管理變數
Devise.setup do |config|
...
config.omniauth :facebook, "KEY", "SECRET"
config.omniauth :google, "KEY", "SECRET"
...
end
到這邊其實就好了,你會疑問,那 link button 呢?,可以到 devise 註冊頁面看一下,應該會有連結了,因為他在原先預設的頁面裡面就有提到這第三方登入,請參考
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br />
<% end -%>
<% end -%>
如果你要任意放你的 link buuton 就用
Google user_google_oauth2_omniauth_authorize_path
Facebook user_facebook_omniauth_authorize_path
如果要擴充其他第三方,就依照此模版繼續新增就可以了
參考來源:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK