2013-10-21 3 views
4

사용자가 LinkedIn, Facebook 및 Twitter에 게시 할 수있는 앱이 있습니다. 사용자가 원하는 많은 공급자로 각 사용자의 계정을 인증하고 싶습니다. 다음과 같습니다Rails & Oauth : 여러 제공 업체

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 

그리고 컨트롤러 인증 방법 :

class User < ActiveRecord::Base 
    ... 
    attr_accessible :provider, :uid, :oauth_token, :oauth_expires_at, :oauth_token_secret, :access_token, :access_token_secret ... 
    ... 
end 

여기 모델 방법입니다 :

내 사용자 모델은 한 번에 하나의 공급 업체에 권한을 부여하는 데 도움이되는 몇 가지 열이 있습니다

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

도움이 될 것입니다. 실제로 여기에서 진행하는 방법을 모릅니다. x (위의 경우에 3이 더 많음)을 :provider 열로 표시하는 것은 다소 우스운 것 같습니다.

답변

5

키는 인증 모델을 사용자 모델과 분리하여 사용자와 ID간에 ​​has_many 관계를 설정할 수 있습니다.

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 

그리고 물론 사용자 모델은 그 참조한다 : 여기에 (omniauth 사용) 오래된 프로젝트에서 내 Identity 모델입니다

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

당신이있어 성가신 가장자리의 경우 많이 있습니다 로그인을 위해 여러 옴니버스 공급자를 허용합니다. 내 기억으로

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을 참조하십시오.

+0

정말로 깊이있는 답변을 보내 주셔서 감사합니다. 체크인을 기다리고 있습니다. –

+0

이것에 대한 나의 해석은 꽤 다르게 나왔지만 그 아이디어에 감사드립니다. –

+1

토큰에 대한 처리 방법을 제시하지 않았습니다. –