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

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

问题描述

我花了几天时间在设计和全方位观看RailsCast,然后通过相关教程设置使用这些宝石的身份验证系统。我认为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与多个验证服务提供商,您需要另外一个模型 - 授权

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

strong>用户模型

There is code for User model

#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

最后你需要覆盖Devise控制器的方法

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天全站免登陆