设计Omniauth - 设置&定义策略

时间:2015-11-14 03:32:46

标签: ruby-on-rails devise omniauth

我试着提出这个问题 - 并没有找到任何帮助。

http://stackoverflow.com/questions/33493369/rails-devise-omniauth-problems-with-setup

我放弃了尝试解决问题并制作了一个全新的应用程序,其中没有别的东西,以便我可以尝试减少其他错误干扰的范围。

在我的新应用中,当我点击新注册/新用户链接时,我现在收到错误。

我已经按照rails casts教程(尝试了大约20个其他人)来进行此设置。 1。5年,我仍然在苦苦挣扎。

问题在于控制器中策略的定义方式。我有4个策略(推特,Facebook,谷歌和linkedin),当我尝试点击链接创建这些帐户的新注册时,我目前正在为每个策略收到不同的错误:

对于Twitter:     未知的行动     无法为Users :: AuthenticationsController

找到操作'twitter'

对于Facebook:

Given URL is not permitted by the Application configuration: One or more of the given URLs is not permitted by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains.

这个错误是因为我无法弄清楚Facebook的文档。它显示了如何使用js登录Facebook,我试图在Rails中使用gems。我并不担心这个错误。我认为它与我的网站没有被定义为本地主机有关,虽然我找不到任何地方,但在Facebook的开发者控制台中的回调网址。我的问题与这个问题没有关系,我会帮助你解决这个问题。

对于LinkedIn:

Safari can’t open the page “https://www.linkedin.com/uas/oauth2/authorization?client_id=LINKEDIN_DEV_ID&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Flinkedin%2Fcallback&response_type=code&scope=r_basicprofile+r_emailaddress&state=3fef961c10410464cd5b0ca49b25112ce53fb65f1a3c794f”.

错误是:“无法解码原始数据”(NSURLErrorDomain:-1015) 我有一个oauth2回调定义为:

http://localhost:3000/users/auth/linkedin/callback

我不知道这里发生了什么。

对于谷歌:

translation missing: en.devise.authentications.user.failure

当我点击此链接并且上面显示错误消息时,新注册视图会刷新。我不知道是什么导致了这个错误。

每个错误都不同。

我的控制器文件夹中有一个名为users的文件夹。在里面我有两个控制器如下:

身份验证控制器:

class Users::AuthenticationsController < Devise::OmniauthCallbacksController
  before_action :set_authentication, only: [:destroy]

  def index
    @authentications = current_user.authentications if current_user
  end


  def create
    omniauth = request.env["omniauth.auth"]
    authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
    if authentication
      sign_in_and_redirect_user(:user, authentication.user.profile)

    elsif current_user
      current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
      redirect_to user.profile_url
    else
      user = User.new
      user.omniauth(omniauth)
      if user.save!
        sign_in_and_redirect_user(:user, user.profile)
      else
        session[:omniauth] = omniauth.except('extra')
        redirect_to new_user_registration_url
      end
    end  
  end

  def destroy
    @authentication.destroy
    respond_to do |format|
      format.html { redirect_to root_path }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_authentication
      @authentication = current_user.authentications.find(params[:id])
    end

注册控制器:

class Users::RegistrationsController < Devise::RegistrationsController 
  #before_filter :check_permissions , :only => [ :new, :create, :cancel ] 
  #skip_before_filter :require_no_authentication 
  # before_action :configure_permitted_parameters, if: :devise_controller?

  def check_permissions
    authorize! :create, resource
  end

  def index
    if params[:approved] == "false"
      @users = User.find_all_by_approved(false)
    else
      @users = User.all
    end
  end

  def create
    super
    session[:omniauth] = nil unless @user.new_record?
  end

  # THIS IS A SUGGESTION FROM SITEPOINT TUTORIAL 
  # protected

  #   def configure_permitted_parameters
  #     devise_parameter_sanitizer.for(:sign_up) << [:first_name, :last_name]
  #   end


  private
    def user_params
          params.require(:user).permit(:first_name, :last_name, :email, :password )
    end

    def build_resource(*args)
        super
        if session[:omniauth]
        @user.apply_omniauth(session[:omniauth])
        @user.valid?
        end
    end  

end

User.rb有

devise
:omniauthable, :omniauth_providers => [:facebook, :linkedin, :twitter, :google_oauth2 ]


 has_many :authentications, :dependent => :delete_all


def apply_omniauth(omniauth)
        self.email = auth['extra']['raw_info']['email']
        authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => auth['credentials']['token'])
    end

def password_required?
  (authentications.empty? || !password.blank?) && super
end

在我的routes.rb中我有:

  devise_for :users,
             :controllers => {
                :registrations => "users/registrations",
                :omniauth_callbacks => "users/authentications"
                # :omniauth_callbacks => 'users/omniauth_callbacks',
           }
  get '/auth/:provider/callback' => 'users/authentications#create'
  get '/sign_out', :to => 'users/authentications#destroy'         

在我的omniauth.rb中,我有:

require 'omniauth-facebook'
require 'omniauth-google-oauth2'
require 'omniauth-twitter'



OmniAuth.config.logger = Rails.logger

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
end

Rails.application.config.middleware.use OmniAuth::Builder do
   provider :facebook, ENV['FACEBOOK_ID'], ENV['FACEBOOK_KEY'],
     :scope => 'public_profile', info_fields: 'id,first_name,last_name,link,email',
     :display => 'popup',
     :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}

end

Rails.application.config.middleware.use OmniAuth::Builder do
   provider :google_oauth2, ENV['YT_CLIENT_ID'], ENV['YT_CLIENT_SECRET'],
            scope: 'profile', image_aspect_ratio: 'square', image_size: 48,
            # {name: "google_login", approval_prompt: ''},
            access_type: 'online'
            #ENV["GOOGLE_APP_ID"], ENV["GOOGLE_APP_SECRET"]
#   {
#         :name => "google",
#         :scope => "userinfo.email, userinfo.profile, plus.me, http://gdata.youtube.com",
#         :prompt => "select_account",
#         :image_aspect_ratio => "square",
#         :image_size => 50
#       }

end

Rails.application.config.middleware.use OmniAuth::Builder do
   if Rails.env == 'production'
     key = ENV["LINKEDIN_PRODUCTION_KEY"]
     secret = ENV["LINKEDIN_PRODUCTION_SECRET"]
   else
     key = "LINKEDIN_DEV_ID"
     secret = "LINKEDIN_DEV_KEY"
   end

   provider :linkedin, key, secret,
     :scope => "r_basicprofile r_emailaddress", 
     :field => ["id", "email-address", "first-name", "last-name" ],
     :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}} 
end

在我的新注册/会话视图中,我有:

<% if devise_mapping.omniauthable? %>
                            <%= link_to icon('facebook', id: 'facebookauth'), user_omniauth_authorize_path(:facebook) %>

                            <%= link_to  icon('google', id: 'googleauth'), user_omniauth_authorize_path(:google_oauth2) %>

                            <%= link_to icon('linkedin', id: 'linkedinauth'), user_omniauth_authorize_path(:linkedin) %>

                            <%= link_to icon('twitter', id: 'twitterauth'), user_omniauth_authorize_path(:twitter) %>
                        <% end %>   

我认为这与认证控制器没有命名策略有关。在其他教程中,我设置了以下内容(现在注释掉了控制器,因为现在使用了一个名为apply_omniauth的方法)。

# def facebook
#   #   @user = User.find_for_facebook_oauth(request.env["omniauth.auth"])
#   #   if @user.persisted?
#   #     # @user.send_admin_mail
#   #     # @user.send_user_welcome_mail

#   #     sign_in @user, :event => :authentication #this will throw if @user is not activated

#   #     if @user.profile
#   #       redirect_to profile_path(@user.profile)
#   #     else
#   #       redirect_to new_profile_path
#   #     end

#   #     # sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
#   #     # set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
#   #   else
#   #     session["devise.facebook_data"] = request.env["omniauth.auth"]
#   #     redirect_to root_path
#   #   end
#   # end


#   # def linkedin
#   #   @user = User.find_for_linkedin_oauth(request.env["omniauth.auth"])

#   #   if @user.persisted?
#   #     # @user.send_admin_mail
#   #     # @user.send_user_welcome_mail

#   #     sign_in @user, :event => :authentication

#   #     if @user.profile
#   #       redirect_to profile_path(@user.profile)
#   #     else
#   #       redirect_to new_profile_path
#   #     end
#   #     #  set_flash_message(:notice, :success, :kind => "LinkedIn") if is_navigational_format?
#   #   else
#   #     session["devise.linkedin_data"] = request.env["omniauth.auth"]
#   #     redirect_to root_path
#   #   end
#   # end


#   # def twitter
#   #   begin
#   #     @user = User.from_omniauth(request.env['omniauth.auth'])
#   #     session[:user_id] = @user.id
#   #     flash[:success] = "Welcome, #{@user.name}!"
#   #   rescue
#   #     flash[:warning] = "There was an error while trying to authenticate you..."
#   #   end
#   #   redirect_to new_profile_path #root_path
#   # end

#   # #
#   def google_oauth2
#      # You need to implement the method below in your model (e.g. app/models/user.rb)
#      @user = User.find_for_google_oauth2(request.env["omniauth.auth"], current_user)

#      if @user.persisted?
#         sign_in @user, :event => :authentication #this will throw if @user is not activated
#         if @user.profile
#           redirect_to profile_path(@user.profile)
#           flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
#         else
#           redirect_to new_profile_path
#         end

#      else
#        session["devise.google_data"] = request.env["omniauth.auth"]
#        redirect_to new_user_registration_url
#      end
#   end

在我完全抛弃rails cast设置之前,有没有一种方法可以使用我已有的代码将当前结构指向指定的提供者?

另一个尝试:

所以我放弃了RailsCast。我试着遵循这个教程:

http://willschenk.com/setting-up-devise-with-twitter-and-facebook-and-other-omniauth-schemes-without-email-addresses/

我对添加一个名为FormUser的新“类”的引用感到困惑。我创建了一个名为form_user.rb的新模型,并按照描述添加了内容。我正在使用Rails 4.我不知道atto-accessor意味着什么,但我已经在我的文件中显示了它。我没有相应的控制器。我也没有在我的用户模型中定义关联(我认为这属于)。

无论如何,我已按照设置进行操作,现在出现此错误:

    TypeError
superclass mismatch for class OmniauthCallbacksController

我的应用程序中定义的每个策略都是一样的。

有没有人看过这个特殊错误&amp;有任何解决方法的提示吗?

我的设置和教程之间的唯一区别是,在我的控制器中,我有一个名为users的文件夹,其中有一个注册控制器和一个omniauth_callbacks控制器。我的路线已经过调整以反映这一层。

devise_for :users, class_name: 'FormUser',
             :controllers => {
                :registrations => "users/registrations",
                # :omniauth_callbacks => "users/authentications"
                :omniauth_callbacks => 'users/omniauth_callbacks',
           }
  get '/auth/:provider/callback' => 'users/authentications#create'
  get '/authentications/sign_out', :to => 'users/authentications#destroy' 


  devise_scope :user do
    get '/users/auth/:provider/upgrade' => 'users/omniauth_callbacks#upgrade', as: :user_omniauth_upgrade
    get '/users/auth/:provider/setup', :to => 'users/omniauth_callbacks#setup'
  end

1 个答案:

答案 0 :(得分:1)

如果其他人正在试图弄清楚他们的头发 - 我没有得到如何做到的答案,但我知道Railscasts太老了他们没用。上面的代码有几个部分不再匹配gem配置。以下教程对您没有帮助。在过去的1。5年里,我尝试过至少20个不同的教程,但我还没找到一个可以上班的教程。 rails cast中的错误包括重定向(不需要再引用'user'等等。如果你依赖于Rails Cast,请放弃。如果有人对找到CURRENT的位置有任何见解,我真的很感激。教程。