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 %>
答案 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