Rails 4、Devise、Omniauth(有多个提供者) [英] Rails 4, Devise, Omniauth (with multiple providers)

查看:15
本文介绍了Rails 4、Devise、Omniauth(有多个提供者)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了几天时间观看有关 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆