oka*_*56k 4 facebook ruby-on-rails oauth oauth-2.0 ruby-on-rails-3
我有一个应用程序允许用户发布到LinkedIn,Facebook和Twitter.我想根据用户的意愿,为每个用户的帐户授权尽可能多的用户帐户.
我的用户模型有一些列可以帮助一次授权一个提供者:
class User < ActiveRecord::Base
...
attr_accessible :provider, :uid, :oauth_token, :oauth_expires_at, :oauth_token_secret, :access_token, :access_token_secret ...
...
end
Run Code Online (Sandbox Code Playgroud)
这是模型方法:
def self.from_omniauth(user, auth)
user.provider = auth.provider
if auth.provider == "facebook"
user.uid = auth.uid
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
elsif auth.provider == "twitter"
# not sure which one twitter uses
user.oauth_token = auth["credentials"]["token"]
user.oauth_token_secret = auth["credentials"]["secret"]
user.access_token = auth["credentials"]["token"]
user.access_token_secret = auth["credentials"]["secret"]
end
user.save!
end
Run Code Online (Sandbox Code Playgroud)
控制器auth方法如下所示:
def authorise
user = User.from_omniauth(current_user, env['omniauth.auth'])
session[:user_id] = current_user.id
redirect_to root_url
end
Run Code Online (Sandbox Code Playgroud)
任何帮助都会很棒!真的不知道怎么从这里开始.有x(在上面的情况下是3,更多的是):provider列的数量似乎有点荒谬.
关键是将身份验证部分与用户模型本身分开,这样您就可以has_many在用户和身份之间建立关系.这是我Identity从旧项目中使用的模型(使用omniauth):
class Identity < ActiveRecord::Base
belongs_to :user
attr_accessible :provider, :uid,
:description, :email, :first_name, :image,
:last_name, :location, :name, :nickname,
:phone, :raw_info, :urls
validates_presence_of :provider, :uid
validates_uniqueness_of :uid, scope: :provider
def self.find_with_omniauth(auth)
find_by_provider_and_uid(auth['provider'], auth['uid'])
end
def self.create_with_omniauth(auth)
create(provider: auth['provider'],
uid: auth['uid'],
name: auth['info']['name'],
email: auth['info']['email'],
nickname: auth['info']['nickname'],
first_name: auth['info']['first_name'],
last_name: auth['info']['last_name'],
location: auth['info']['location'],
description: auth['info']['description'],
image: auth['info']['image'],
phone: auth['info']['phone'],
urls: auth['info']['urls'].to_json,
raw_info: auth['extra']['raw_info'].to_json
)
end
end
Run Code Online (Sandbox Code Playgroud)
然后用户模型当然应该参考:
class User < ActiveRecord::Base
...
has_many :identities, dependent: :destroy
...
Run Code Online (Sandbox Code Playgroud)
当你允许多个omniauth提供程序登录时,有很多讨厌的边缘情况.因此,要创建新的登录(会话),您可以执行以下操作:
class SessionsController < ApplicationController
def create
auth = request.env['omniauth.auth']
origin = request.env['omniauth.origin']
destination = origin.blank? ? root_path : origin
@identity = Identity.find_with_omniauth(auth)
@identity = Identity.create_with_omniauth(auth) if @identity.nil?
if signed_in?
if @identity.user == current_user
# Identity is already associated with this user
redirect_to destination, notice: "Already logged in and linked"
else
# Identity is not associated with the current_user
@old_user = @identity.user
if @old_user
current_user.posts << @old_user.posts
current_user.galleries << @old_user.galleries
current_user.favorites << @old_user.favorites
end
@identity.user = current_user
@identity.save()
@old_user.destroy if @old_user && @old_user.identities.blank?
redirect_to destination, notice: "Account was successfully linked"
end
else
if @identity.user.present?
# Identity has a user associated with it
self.current_user = @identity.user
redirect_to destination
else
# No user associated with the identity so create a new one
user = User.create_with_omniauth(auth['info'])
@identity.user = user
@identity.save()
self.current_user = @identity.user
redirect_to destination, notice: "Registration successful"
end
end
end
def destroy
self.current_user = nil
redirect_to root_url, notice: "Signed out successfully"
end
def omniauth_failure
origin = request.env['omniauth.origin']
destination = origin.blank? ? root_path : origin
redirect_to destination, alert: "Connection failed"
end
end
Run Code Online (Sandbox Code Playgroud)
我记得,当我编写上面的代码时,我倾向于写了一篇关于这个主题的文章.有关更多信息和想法,请参阅https://github.com/intridea/omniauth/wiki/Managing-Multiple-Providers.
| 归档时间: |
|
| 查看次数: |
1275 次 |
| 最近记录: |