如何在使用Omniauth Identity时设置身份验证表?

时间:2017-05-02 15:30:19

标签: ruby-on-rails authentication omniauth

我正在尝试将Omniauth Identity添加到我的Rails应用程序中。这样我最终可以支持本地和OAuth登录。

我一直在使用以下要点获取有关如何使其发挥作用的信息 - https://gist.github.com/stefanobernardi/3769177

问题是,当在数据库的Users表中注册新用户时,authentications表没有填充user_id或提供者。这意味着登录失败,因为系统无法使用provider从数据库中获取正确的用户。

models/authentication.rb

class Authentication < ApplicationRecord

  attr_accessor :provider, :uid, :user_id
  belongs_to :user


  def self.find_with_omniauth(auth)
    find_by_provider_and_uid(auth['provider'], auth['uid'])
  end

  def self.create_with_omniauth(auth)
    create(uid: auth['uid'], provider: auth['provider']) # and other data you might want from the auth hash
  end

end

controller/sessions_controller.rb

class SessionsController < ApplicationController

  skip_before_action :verify_authenticity_token, only: :create

  def new
  end


  def create_old
    user = User.find_by(email: params[:session][:email].downcase)
    if user && user.authenticate(params[:session][:password])
      log_in user
      params[:session][:remember_me] == '1' ? remember(user) : forget(user)
      redirect_back_or user
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end


  def create

    auth = request.env['omniauth.auth']

    # Find an authentication or create one
    if @authentication.nil?

      # If no authentication was found, create new one here
      @authentication = Authentication.create_with_omniauth(auth)

    end

    if logged_in?

      if @authentication.user == current_user

        # User is signed in so they are trying to link an authentication with their
        # account.  But an authentication has been found and the user associated with it
        # is the current user.  So the authentication is already associated with the 
        # this user, therefore display an error
        redirect_to root_path, notice: "You have already linked this account"
      else

        # The authentication is not associated with the current_user to associate
        # the authentication
        @authentication.user = current_user
        @authentication.save
        redirect_to root_path, notice: "Account successfully authenticated"
      end
    else # no user is signed in

      if @authentication.user.present?

        # The authentication that has been found had a user associated with it so 
        # just lof them in 
        self.current_user = @authentication.user
        redirect_to root_path, notice: "Signed in"
      else

        # The authentication has no user assigned and there is not user signed in
        # The decision here is to create a new account for the user
        # Check for the Omniauth Idenitity provider which is local auth
        if @authentication.provider == 'identity'

          u = User.find(@authentication.uid)

          # if using the identity provior then the user is local so just find
          # in the database
        else

          # Create a new user in the databse using the hash of information from the 
          # omniauth
          u = User.create_with_omniauth(auth)
        end

        # Now can link the authentication with the user
        u.authentications << @authentication
        self.current_user = u
        redirect_to root_path, notice: "Welcome"
      end

    end
  end

  def destroy
    log_out if logged_in?
    redirect_to root_url
  end

  def failure
    redirect_to root_path, alert: "Authentication failed, please try again"
  end
end

数据库的架构是

ActiveRecord::Schema.define(version: 20170426182907) do

  create_table "authentications", force: :cascade do |t|
    t.integer  "user_id"
    t.string   "provider"
    t.string   "uid"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_authentications_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at",      null: false
    t.datetime "updated_at",      null: false
    t.string   "password_digest"
    t.string   "remember_digest"
    t.index ["email"], name: "index_users_on_email", unique: true
  end

end

用户在Users表中创建没有问题,authentication对象容纳了提供者信息,它只是没有进入身份验证表。创建记录,而不是提供者。

很高兴提供更多信息,但不希望使用(可能)无关信息使帖子过长。我确信这是一件非常简单的事情,我错过了,而且没有正确地将事物连接在一起。

1 个答案:

答案 0 :(得分:0)

这是由models/authentication.rb文件

中的以下行引起的
   attr_accessor :uid, :provider, :user_id

通过设置此设置,数据库中未设置provider。从此列表中删除它会将数据保留在数据库中。