2014-01-21 86 views
20

我花了几天在devise和omniauth上观看RailsCasts,然后通过相关教程来设置使用这些gem的认证系统。我认为RailsCasts已经过时了,并且试图用其他教程来弥补差距正在创造各种问题。Rails 4,Devise,Omniauth(与多个提供者)

请任何人都可以提出一个当前的教程,我可以用它作为实现这个系统的基础。我有单独的用户和身份验证模型(用户具有许多身份验证)。

我真的很喜欢在rails 4上使用devise和omniauth(CanCan的能力),但在试图找到一个基本设置(使用psql作为数据库)时,我的头发已经褪去。

在你初始化
+0

官方文档是要走的路 – emaillenin

+0

我有这个相同的问题...任何解决方案? – 2014-02-20 21:08:36

+0

我发现这个:https://github.com/mohitjain/social-login-in-rails,但我不认为它可以解决从Twitter连接用户/身份验证的问题。 Twitter不共享电子邮件,他的用户模型使用电子邮件查找以前的记录。嗯......希望有人能找到一个很好的解决方案。 – robertwbradford

回答

29

东西要使用设计不同,需要1多个模型的多个身份验证提供者 - 授权

#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 

,并在结束时,你需要重写为设计控制器

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方法,因为它不提供用户邮件,你应该以其他方式保存它的credentails。

你也应该在路线

devise_for :users, 
      :controllers => { 
      :omniauth_callbacks => 'users/omniauth_callbacks', 
      } 
+6

感谢分享代码!只是简单的说明,授权与认证不同,omniauth关心的是用户认证(你是谁),而像权威人士和cancan可以处理授权的宝石(我们知道你是谁,以下是你能做和不能做的)。只是为了澄清新手进行编程的事情。 –

+2

非常感谢您的支持。实际上很难找到一个完整的,最新的工作解决方案。 – ahnbizcad

+0

在'users'下嵌套omniauth回调是做什么的,为什么它是必要的? – ahnbizcad

2

尝试做这样的

#config/initializers/devise.rb 
    #provider1 
    config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET'], 
    :site => 'https://graph.facebook.com/', 
    :authorize_path => '/oauth/authorize', 
    :access_token_path => '/oauth/access_token', 
    :scope => 'email, user_birthday, read_stream, read_friendlists, read_insights, read_mailbox, read_requests, xmpp_login, user_online_presence, friends_online_presence, ads_management, create_event, manage_friendlists, manage_notifications, publish_actions, publish_stream, rsvp_event, user_about_me, user_activities, user_birthday, user_checkins, user_education_history, user_events, user_groups, user_hometown, user_interests, user_likes, user_location, user_notes, user_photos, user_questions, user_relationships, user_relationship_details, user_religion_politics, user_status, user_subscriptions, user_videos, user_website, user_work_history' 

    #provider2 
    config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'], 
    :scope => { 
    :secure_image_url => 'true', 
    :image_size => 'original', 
    :authorize_params => { 
     :force_login => 'true' 
    } 
    } 

    #provider3 
    config.omniauth :google_oauth2, ENV["GOOGLE_KEY"], ENV["GOOGLE_SECRET"] 
+1

这对我来说并不适用于强制Twitter使用户重新登录。它使用的是我以前在浏览器上的某个时间之前登录过的帐户。我试图让用户可以将多个帐户链接到他们的网站帐户。 – Dex

+0

你可以创建一个auth控制器,属于一个用户和一个用户has_many auths – MZaragoza

+0

我找到了答案。取出':scope =>',使用'omniauth-twitter' gem可以很好地工作。范围是面向Facebook和其他一些服务的。 – Dex

3

一些变化,您应该给这个宝石一试。 https://github.com/AlexanderZaytsev/domp 快速且易于集成。我在30米左右有一个工作设置。

+0

那个宝石没有为我工作,可以请你分享你的例子。 – fenec

+0

这是我遇到的问题。 https://github.com/AlexanderZaytsev/domp/issues/16 – fenec

+0

我正在使用这颗宝石。虽然有一个小问题。当我转到(本地主机:3000 /用户/身份验证/脸书)它给我没有路线匹配错误。 但用耙指令我可以看到它定义在那里 – zaingz

相关问题