加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – Rails&Oauth:多个提供商

发布时间:2020-12-17 02:39:31 所属栏目:百科 来源:网络整理
导读:我有一个应用程序允许用户发布到LinkedIn,Facebook和Twitter.我想根据用户的意愿,为每个用户的帐户授权尽可能多的用户帐户. 我的用户模型有一些列可以帮助一次授权一个提供者: class User ActiveRecord::Base ... attr_accessible :provider,:uid,:oauth_to
我有一个应用程序允许用户发布到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

这是模型方法:

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

控制器auth方法如下所示:

def authorise
  user = User.from_omniauth(current_user,env['omniauth.auth'])
  session[:user_id] = current_user.id
  redirect_to root_url
end

任何帮助都会很棒!真的不知道怎么从这里开始.有x(在上面的情况下是3,更多的是)数量:提供者列似乎有点荒谬.

解决方法

关键是将身份验证部分与用户模型本身分开,这样您就可以在用户和身份之间建立一个has_many关系.这是来自旧项目的我的身份模型(使用omniauth):

class Identity < ActiveRecord::Base
  belongs_to :user

  attr_accessible :provider,: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

然后用户模型当然应该参考:

class User < ActiveRecord::Base
  ...
  has_many :identities,dependent: :destroy
  ...

当你允许多个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

我记得,当我编写上面的代码时,我倾向于写了一篇关于这个主题的文章.有关详细信息,请参阅https://github.com/intridea/omniauth/wiki/Managing-Multiple-Providers&想法.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读