登录表单未登录 - 会话返回Null Limit 1

时间:2016-02-16 07:03:33

标签: ruby-on-rails ruby-on-rails-4

Rails在这里学习,通过构建一个有两半的应用程序来尝试新事物,另一半是另一半学生。

已经建立了企业以拥有自己的控制器和模型,并且学生拥有自己的控制器和模型,其中两个用户类型都通过相同的表单登录。 (我知道我可以用更基于角色的方式创建它,使用列来表示用户类型,但从学习的角度来看,隔离对我来说更有意义)

我的问题是,当以新用户身份注册时,它会正常登录,但作为返回用户(学生或公司),它从不登录,即使在输入新凭据时登录页面也会继续呈现。

据我所知,这是因为在搜索数据库以验证用户而不是通过电子邮件进行搜索时,其搜索电子邮件的位置为NULL LIMIT 1 ...

SELECT" corporates"。* FROM" corporates"在哪里"企业"。"电子邮件" IS NULL LIMIT 1

任何帮助都会非常感激,学习rails肯定是一段旅程!

希望我已经发布了足够的组件,如果我错过了任何内容,请告诉我。

会话控制器

class SessionsController < ApplicationController

  def new
  end


  def create
      if
        @corporate = Corporate.authenticate(params[:email], params[:password])
        session[:corporate_id] = @corporate.id
        flash[:notice] = "Welcome back, #{corporate.firstname}!"
        redirect_to (session[:intended_url] || @corporate)
        session[:intended_url] = nil

      elsif 
        @student = Student.authenticate(params[:email], params[:password])

        if params[:remember_me]
              cookies.permanent[:auth_token] = student.auth_token
            else
              cookies[:auth_token] = student.auth_token
        end
        flash[:notice] = "Welcome back, #{student.firstname}!"
        redirect_to (session[:intended_url] || student)
        session[:intended_url] = nil
      else
        flash.now[:warning] = "Kindly login with your email and password!"
        redirect_to '/login'
        #render :new
      end 
    end




 def destroy
    if current_corporate
      session.delete(:student_id) || cookies.delete(:auth_token)
    else current_corporate
      session[:corporate_id] = nil
    end
    redirect_to root_url, notice: "You have signed out!"
  end


  def logged_in?
    !current_corporate.nil?
  end


end

Corporates Controller

class CorporatesController < ApplicationController


  def index
      @Corporates = corporate.paginate(page: params[:page], :per_page => 5).includes(:profile)
  end

  def show
  if params[:id] 
      @corporate = Corporate.find(params[:id])
      # .includes(:profile)
    else 
      @corporate = current_corporate
    end
    @searches = Search.where(corporate_id: @corporate).includes(:state, city: [:profile])

  end


  def new
    @corporate = Corporate.new
    #@corporateprofile = Corporateprofile.new

  end

  def create
    @corporate = Corporate.new(corporate_params)
    #@corporateprofile = Corporateprofile.new(corporate_idparams)

    if @corporate.save
      session[:corporate_id] = @corporate.id
      redirect_to @corporate
      #redirect_to corporate_path(current_corporate)
    else
      render :new
    end
  end

private
  def corporate_params
    params.require(:corporate).permit(:firstname, :lastname, :email, :password)
  end

end

企业模式

class Corporate < ActiveRecord::Base

  mount_uploader :corp_image, CorpImageUploader
  mount_uploader :logo, LogoUploader
  has_secure_password

#made by tom to create profile
 after_create :build_profile

 #made by tom to link tables
 has_many :searches, dependent: :destroy
 has_one :corporate_profile,autosave: true, dependent: :destroy



  validates :password, length: { minimum: 8, allow_blank: true }
  validates :firstname, presence: true
  validates :lastname, presence: true
  validates :email, presence: true,
                  format: /\A\S+@\S+\z/,
                  uniqueness: { case_sensitive: false }



  COMPANY_SIZE = ["1 - 10 Employees", "11 - 50 Employees", "51 - 100 Employees", "101 - 200 Employees", "201 - 500 Employees", "501 - 1000 Employees", "1001 - 5000 Employees", "5001 - 10000 Employees", "10001 - 20000 Employees", "20001 - 50000 Employees", "50001 - 100000 Employees", "100001 - 200000 Employees", "200000+ Employees"]
  INDUSTRY = ['Accounting', 'Airlines/Aviation', "Alternative Disputs Resolution", "Alternative Medicine", "Animation", "Apparel & Fashion", 
    "Architecture & Planning", "Arts & Crafts", "Automotive", "Banking", "Biotechnology", "Broadcast Media", "Building Materials", "Capital Markets", "Commercial Real Estate",
   "Computer Software", "Computer hardware & Network Security", "Construction", 'Consumer Electronics', 'Consumer Services', "Dairy", "Education Management", "E-Learning", "Entertainment", "Information Technology and Services",
   "Hospital & Health Care", "Import and Export", "Internet", "Government", "Legal", "Management Consulting", "Marketing and Advertising", "Military", "Nonprofit Organization Management",
   "Oil & Energy","Professional Training & Coaching", "Restaurants", "Research", "Security and Investigations", "Sports", "Staffing and Recruiting", "Transportation", "Venture Capital & Private Equity", "Other"]
  #validates :sex, inclusion: { in: SEX }

  before_create {generate_token(:auth_token)}

  def send_password_reset
    generate_token(:password_reset_token)
    self.password_reset_sent_at = Time.zone.now
    save!
    CorporateMailer.password_reset(self).deliver
  end

  def generate_token(column)
    begin
      self[column] = SecureRandom.urlsafe_base64
    end while Corporate.exists?(column => self[column])
  end

  def gravatar_id
    Digest::MD5::hexdigest(email.downcase)
  end

  def self.authenticate(email_or_username, password)
    corporate = Corporate.find_by(email: email_or_username)
    corporate && corporate.authenticate(password)
  end

  def should_generate_new_friendly_id?
      new_record?
  end

  #made by tom to build profile
  def build_profile
    CorporateProfile.create(corporate: self) # Associations must be defined correctly for this syntax, avoids using ID's directly.
  end

end

应用程序控制器

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  before_filter :expire_hsts
  #helper_method :current_user


private

  def require_signin_corporate
    unless current_corporate
      session[:intended_url] = request.url
      redirect_to new_session_url, alert: "You need to login or register as corporate to post job"
    end
  end
  helper_method :require_signin_corporate

  def require_signin
    unless (current_student || current_corporate)
      session[:intended_url] = request.url
      redirect_to new_session_url, alert: "You need to sign in to have access"
    end
  end

  def require_signin_student
    unless current_student
      session[:intended_url] = request.url
      redirect_to new_session_url, alert: "You need to sign in to have access"
    end
  end
  helper_method :require_signin_student

  def current_corporate
    #@current_corporate ||= Corporate.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
    @current_corporate ||= Corporate.find(session[:corporate_id]) if session[:corporate_id]
  end
  helper_method :current_corporate

  def current_student
    @current_student ||= Student.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
    #@current_student ||= Student.find(session[:student_id]) if session[:student_id]
  end

  helper_method :current_student


  def current_student?(student)
    current_student == student
  end
  helper_method :current_corporate?

  def current_corporate?(corporate)
    current_corporate == corporate
  end

  helper_method :current_student?

  def correct_student
    @student = Student.friendly.find(params[:id])
    unless current_student?(@student)
      redirect_to root_url
    end
  end

  def correct_student?
     #current_student == correct_student
     @correct_student == @student
  end
  helper_method :correct_student?

  def correct_corporate
    @corporate = Corporate.friendly.find(params[:id])
    unless current_corporate?(@corporate)
      redirect_to root_url
    end
  end

  def correct_corporate?
     #current_corporate == correct_corporate
     @correct_corporate == @corporate
  end
  helper_method :correct_corporate?

  def require_admin
    unless current_student_admin? || current_corporate_admin?
      redirect_to root_url, alert: "Unauthorized access!"
    end
  end

  def current_corporate_admin?
    current_corporate && current_corporate.admin?
  end

  def current_student_admin?
    current_student && current_student.admin?
  end

  helper_method :current_corporate_admin?, :current_student_admin?

  def require_author
    unless current_corporate_author?
      redirect_to root_url, alert: "Unauthorized access!"
    end
  end

  def current_corporate_author?
    current_corporate && current_corporate.author?
  end

  helper_method :current_corporate_author?

  def require_pro
    unless current_corporate_pro?
      redirect_to root_url, alert: "Unauthorized access!"
    end
  end

  def current_corporate_pro?
    current_corporate && current_corporate.pro?
  end

  helper_method :current_corporate_pro?


  def expire_hsts
    response.headers["Strict-Transport-Security"] = 'max-age=0'
  end


end

登录表格(会议表格)

 <%= bootstrap_form_for(:session, url: session_path) do |f| %> 

    <div class="field">
      <%= f.email_field :email, :placeholder => "Email" %> 
    </div>

    <div class="field">
      <%= f.password_field :password, :placeholder => "Password" %>
      <%= f.submit "Log in", class: "btn btn-primary block full-width m-b" %> 

    </div>


    <a href="#">
        <small>Forgot password?</small>
    </a>

    <p class="text-muted text-center">
        <small>Do not have an account?</small>
    </p>
    <a class="btn btn-sm btn-white btn-block" href="/signup">Create an account</a>

    <% end %>

1 个答案:

答案 0 :(得分:1)

使用两个不同的类进行身份验证会使事情变得更复杂一些 - 并且无论如何都要正确授权。

使用基于角色的系统通常更可取。它有助于保持授权和身份验证的分离,并将大大简化与用户打交道的逻辑,并大大减少重复数量。

重构

但是,让我们来看看如何开始修复当前的设置。

您可能要做的第一件事是对其进行流线化,以便您的应用程序对这两个类使用相同的逻辑。并确保您只具有在应用程序中的某个位置从会话中序列化/清除用户的逻辑。

# app/helpers/sessions_helper.rb
module SessionsHelper
  def current_user
    if session[:corporate_id]
      resource_class = Corporate
      id = session[:corporate_id]
    elsif session[:student_id]
      resource_class = Student
      id = session[:student_id]
    end
    @current_user ||= resource_class.find(id)
  end

  def signed_in?
    current_user.present?
  end

  def sign_in!(resource)
    reset_session # this helps combat session fixation attacks
    session[@resource.model_name.i18n_key] = resource.id
    @current_user = resource
  end

  def sign_out!
    reset_session
  end
end

一个关键点是我们在登录和退出用户时都使用reset_session。它使当前会话标识符无效并生成新的会话标识符,是对session fixation/hijacking attacks的重要防御。

我们还设置了一个current_user,它并不关心它是Corporate还是Student。要检查你可以做到:

current_user.is_a?(Corporate)

让我们在控制器中包含这个帮助器:

class ApplicationController < ActionController::Base
  include SessionsHelper
  # ...
end

让我们以同样的方式重构SessionsController:

class SessionsController

  # ...
  def create
    @resource = Corporate.authenticate(params[:email], params[:password])
    @resource ||= Student.authenticate(params[:email], params[:password])

    if @resource 
       # we need to store this since we are resetting the session.
      intended_url = session[:intended_url]
      sign_in!(@resource)
      flash[:success] = "Welcome back, #{ @resource.firstname }!"
      redirect_to(intended_url || root_path)
    else
      # don't use flash.now when redirecting!
      flash[:warning] = "Kindly login with your email and password!"
      redirect_to '/login'
    end
  end 

  def destroy
    if signed_in?
      sign_out!
      redirect_to root_path, notice: 'You have been signed out!'
    else
      redirect_to root_path, error: "You are not signed in!"
    end
  end
end

您还想更改您的Corporates / StudentsController创建方法,以便它使用 相同的登录逻辑:

class CorporatesController

  #...

  def create
    @corporate = Corporate.new(corporate_params)
    #@corporateprofile = Corporateprofile.new(corporate_idparams)

    if @corporate.save
      sign_in! @corporate
      redirect_to @corporate
    else
      render :new
    end
  end
end