Rails 4、Devise、Omniauth(有多个提供者) [英] Rails 4, Devise, Omniauth (with multiple providers)
问题描述
我花了几天时间观看有关 devise 和 omniauth 的 RailsCasts,然后浏览相关教程以设置使用这些 gem 的身份验证系统.我认为 RailsCast 已经过时了,试图弥补与其他教程的差距会产生各种各样的问题.
I have spent days watching the RailsCasts on devise and omniauth and then going through related tutorials for setting up an authentication system that uses these gems. I think the RailsCasts are out of date and trying to patch the gaps with other tutorials is creating all kinds of issues.
请任何人都可以推荐一个当前的教程,我可以将其用作实现该系统的基础.我有单独的用户和身份验证模型(用户有很多身份验证).
Please can anyone suggest a current tutorial that I can use as a basis for implementing this system. I have separate user and authentications models (with users having many authentications).
我真的很想在 rails 4 上使用 devise 和 omniauth(使用 CanCan 来实现能力),但我在试图找到基本设置(使用 psql 作为数据库)时费力不讨好.
I'd really like to use devise and omniauth (with CanCan for abilities) on rails 4 but am tearing my hair out in trying to find a basic setup (using psql as a database).
推荐答案
要将 Devise 与多个身份验证提供程序一起使用,您还需要 1 个模型 - 授权
To use Devise with multiple auth providers you need 1 more model - Authorization
#authorization.rb
# == Schema Information
#
# Table name: authorizations
#
# id :integer not null, primary key
# user_id :integer
# provider :string(255)
# uid :string(255)
# token :string(255)
# secret :string(255)
# created_at :datetime
# updated_at :datetime
# profile_page :string(255)
#
class Authorization < ActiveRecord::Base
belongs_to :user
end
有用户模型的代码
#user.rb
SOCIALS = {
facebook: 'Facebook',
google_oauth2: 'Google',
linkedin: 'Linkedin'
}
has_many :authorizations
def self.from_omniauth(auth, current_user)
authorization = Authorization.where(:provider => auth.provider, :uid => auth.uid.to_s,
:token => auth.credentials.token,
:secret => auth.credentials.secret).first_or_initialize
authorization.profile_page = auth.info.urls.first.last unless authorization.persisted?
if authorization.user.blank?
user = current_user.nil? ? User.where('email = ?', auth['info']['email']).first : current_user
if user.blank?
user = User.new
user.skip_confirmation!
user.password = Devise.friendly_token[0, 20]
user.fetch_details(auth)
user.save
end
authorization.user = user
authorization.save
end
authorization.user
end
def fetch_details(auth)
self.name = auth.info.name
self.email = auth.info.email
self.photo = URI.parse(auth.info.image)
end
最后你需要覆盖设计控制器的方法
And at the end you need to override methods for Devise controller
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
user = User.from_omniauth(env['omniauth.auth'], current_user)
if user.persisted?
sign_in user
flash[:notice] = t('devise.omniauth_callbacks.success', :kind => User::SOCIALS[params[:action].to_sym])
if user.sign_in_count == 1
redirect_to first_login_path
else
redirect_to cabinet_path
end
else
session['devise.user_attributes'] = user.attributes
redirect_to new_user_registration_url
end
end
User::SOCIALS.each do |k, _|
alias_method k, :all
end
end
如果您需要一些供应商,例如Twitter 您需要覆盖 twitter 方法,因为它不提供用户电子邮件,您应该以其他方式保存它的凭据.
If you need some for providers, e.g. Twitter you need to override twitter method, because it doesn't provide user email and you should save it's credentails in some other way.
你也应该对路线做一些改变
Also you should make some changes in routes
devise_for :users,
:controllers => {
:omniauth_callbacks => 'users/omniauth_callbacks',
}
这篇关于Rails 4、Devise、Omniauth(有多个提供者)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!