Rails,Devise和Omniauth – 设置问题

我正在尝试(再次)使用Rails 4,devise和omniauth设置身份validation。

我试着按照这篇文章中的例子: Rails 4,Devise,Omniauth(有多个提供者)

我安装了这些gem:

gem 'devise' gem 'omniauth-google-oauth2' gem 'omniauth-facebook' gem 'omniauth-twitter' gem 'omniauth-linkedin-oauth2' gem 'oauth2' 

我有一个用户模型和一个身份validation模型。

我有:

User.rb:

  has_many :authentications def disapprove self.approved = false end def approve self.approved = true end 

SOCIALS = {facebook:’Facebook’,google_oauth2:’Google’,linkedin:’Linkedin’}

 def self.from_omniauth(auth, current_user) authentication = Authentication.where(:provider => auth.provider, :uid => auth.uid.to_s, :token => auth.credentials.token, :secret => auth.credentials.secret).first_or_initialize authentication.profile_page = auth.info.urls.first.last unless authentication.persisted? if authentication.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 authentication.user = user authentication.save end authentication.user end def fetch_details(auth) self.first_name = auth.info.first_name self.last_name = auth.info.last_name self.email = auth.info.email self.image = URI.parse(auth.info.image) end 

Authentication.rb

  belongs_to :user 

的routes.rb

 devise_for :users, :controllers => { :registrations => "users/registrations", :omniauth_callbacks => 'users/omniauth_callbacks', } 

用户/ registrations_controller

 class Users::RegistrationsController  [ :new, :create, :cancel ] #skip_before_filter :require_no_authentication 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 @user = User.new(user_params) #(params[:user]) respond_to do |format| if resource.save # Tell the UserMailer to send a welcome email after save # {@user.send_admin_mail # @user.send_user_welcome_mail} format.html { redirect_to(profile_path(@user.profile))} #, notice: 'We have received your registration. We will be in touch shortly.') } #format.json { render json: root_path, status: :created, location: @user } else #format.html { redirect_to(root_path, alert: 'Sorry! There was a problem with your registration. Please contact us to sort it out.') } format.html { render action: 'new' } format.json { render json: @user.errors, status: :unprocessable_entity } end end end private def user_params params.require(:user).permit(:first_name, :last_name, :email, :password ) end # protected # def after_sign_up_path_for(resource) # 'subscribers/new' # end end 

用户/ Omniauth_callbacks控制器

class Users :: OmniauthCallbacksController <Devise :: OmniauthCallbacksController

  # try again following https://stackoverflow.com/questions/21249749/rails-4-devise-omniauth-with-multiple-providers 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 profile_path(@user.profile) else redirect_to root_path end else session['devise.user_attributes'] = user.attributes redirect_to root_path end end User::SOCIALS.each do |k, _| alias_method k, :all end end 

设计/新注册视图说:

  
{:class => 'deviselabels'}, autofocus: true, required: false, :input_html => {:maxlength => 15, :size => 40, class: 'lineitemdevise'} %> {:class => 'deviselabels'}, required: false, :input_html => {:maxlength => 15, :size => 40, class: 'lineitemdevise'} %> {:class => 'deviselabels'}, required: false, autofocus: false, placeholder: "Please use your work or university address", :input_html => {:maxlength => 55, :size => 40, class: 'lineitemdevise'} %> {:class => 'deviselabels'}, required: false, placeholder: "Minimum 8 characters", :input_html => {:maxlength => 15, :size => 40, class: 'lineitemdevise'} %>
"dcpb" %>

我有另一个名为profile.rb的模型。

 profile belongs_to user 

问题:

  1. 这些都不起作用。 当我点击每个社交媒体登录链接时,该页面将跳转到通过电子邮件表单注册。

heroku日志错误消息说:

 (facebook) Authentication failure! invalid_credentials: OAuth2::Error, : 2015-11-03T07:05:48.237549+00:00 app[web.1]: {"error":{"message":"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request","type":"OAuthException","code":100,"fbtrace_id":"HD3mnzmSTEw"}} 
  1. 当我使用电子邮件和密码通过电子邮件表单完成注册时,会识别用户名(导航栏中显示Hello,但是当我进入rails控制台时,用户未列出。

此外,当我单击用户名时,我收到一条错误消息,指出该配置文件不存在。 heroku日志说:

 (Couldn't find Profile with 'id'=3) 
  1. 是否需要另一个步骤才能使社交媒体注册工作以创建新用户?

我的下一步尝试:

我已经改变了以上所有内容并按照Railscastsvideo中的方法再次尝试。

我现在使用用户模型和身份validation模型。

在user.rb中,我有:

  has_many :authentications, :dependent => :delete_all def apply_omniauth(omniauth) authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => auth['credentials']['token']) end 

authentication.rb

 belongs_to :user def self.from_omniauth(auth) where(auth.slice(:provider, :uid)).first_or_create do | user | authentication.provider = auth.provider authentication.uid = auth.uid authentication.user.first_name = auth.first_name authentication.user.last_name = auth.last_name authentication.user.image = auth.info.image end end 

Authentications_controller:

 class AuthenticationsController  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 authentications_url } 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 end 

在routes.rb中,我有:

  devise_for :users, :controllers => { :registrations => "users/registrations", } patch '/auth/:provider/callback' => 'authentications#create' 

Omniauth.rb

要求’omniauth-facebook’需要’omniauth-google-oauth2′

OmniAuth.config.logger = Rails.logger

  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'}} 

然后,当我尝试这个时,我得到这个错误:

 (facebook) Authentication failure! invalid_credentials: OAuth2::Error, : 2015-11-05T06:4839+00:00 app[web.1]: {"error":{"message":"Error validating verification code. Please make sure your redirect_uri is identical to the one you used in the OAuth dialog request","type":"OAuthException","code":100,"fbtrace_id":"CrvXN22Z"}} 

我发现错误消息的下一部分是奇怪的,因为它引用了我不再使用的回调控制器(整个事情被注释掉,并且没有路由)。

 Authentication failure! invalid_credentials: OAuth2::Error, : 2015-11-05T08:24:16.010951+00:00 app[web.1]: Processing by Devise::OmniauthCallbacksController#failure as HTML 2015-11-05T08:24:16.012648+00:00 app[web.1]: Redirected to http://www.dder.com/users/sign_in 

进一步尝试

我已经尝试用omniauth设置设计超过1。5年了。 这是我最近的尝试(遵循sitepoint.com/rails-authentication-oauth-2-0-omniauth上的Sitepoint教程)。 我之前尝试过使用本教程并没有取得任何成功,所以我做了一些调整,尝试将其调整到其他教程的某些方面。

我现在有:

user.rb

  has_many :authentications, :dependent => :delete_all def apply_omniauth(omniauth) authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => auth['credentials']['token']) end 

authentication.rb

 belongs_to :user def self.from_omniauth(auth) where(auth.slice(:provider, :uid)).first_or_create do | user | authentication.provider = auth.provider authentication.uid = auth.uid authentication.user.first_name = auth.first_name authentication.user.last_name = auth.last_name authentication.user.image = auth.info.image end end 

认证控制器

  class AuthenticationsController  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 authentications_url } 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 end 

注册控制器

 class Users::RegistrationsController  [ :new, :create, :cancel ] #skip_before_filter :require_no_authentication # before_action :configure_permitted_parameters, if: :devise_controller? # Suggestion from Sitepoint tutorial - not currently implemented because not sure about the difference between this and set params. 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 

路线

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

我可以用以下方法查看这些路线

 rake routes | grep auth user_omniauth_authorize GET|POST /users/auth/:provider(.:format) authentications#passthru {:provider=>/facebook|linkedin|twitter|google_oauth2/} user_omniauth_callback GET|POST /users/auth/:action/callback(.:format) authentications#:action GET /auth/:provider/callback(.:format) authentications#create 

视图中的新注册部分

  

我真的不确定这条路是从哪里来的。 不知道为什么它被命名为它。

视图中的新会话部分

   

当前错误:

 AbstractController::ActionNotFound at /users/auth/twitter/callback The action 'twitter' could not be found for AuthenticationsController 

Devise带有一个开箱即用的解决方案,可与omniuth集成。 您可以查看以下url:1。https://www.digitalocean.com/community/tutorials/how-to-configure-devise-and-omniauth-for-your-rails-application这个显示与DigitalOcean的集成,但可以扩展到其他人。 2. https://github.com/plataformatec/devise/wiki/OmniAuth%3A-Overview这是来自设计维基

希望能帮助到你

有一个名为dom的gem专门用于管理具有多个提供者的Devise。 它使事情致命简单!

另外,我认为你应该阅读这些文章。 我相信你可以用他们解决所有问题:

  1. 设计OmniAuth:概述
  2. OmniAuth管理多个探测器