簡體   English   中英

Ruby on Rails 4:使用多個設計模型進行身份驗證后授權

[英]Ruby on Rails 4: authorisation after authentication with multiple Devise models

我創建了一個簡單的 Ruby on Rails 4 應用程序,其中包含一些簡單的模型和一個部署在我的測試 VPS 上的 PosgreSQL 數據庫。 然后我使用 Rails 生成器創建了三個設計模型。

我選擇了單獨的 Devise 模型,因為這些模型彼此完全不同。 單表繼承方法是沒有問題的。

我知道使用任何設計模型,我都可以在現場執行身份驗證、注冊“設計”用戶等。這些東西有效。

現在我打算設置一個地方來制作我的授權東西。 根據我使用 Google 的發現,我放棄了 CanCan,因為目前 Rails 4 不支持它。

所以我找到的最合適的選項是簡單地使用before_filter和自定義身份驗證方法,它反過來檢查current_user類型或其存在,並返回是否可以使用。

這是我已經嘗試過的示例偽代碼,它看起來有效。

before_filter :custom_authentication!

def custom_authentication!
  if current_admin
    redirect_to "admin_page"
  elsif current_monkey
    redirect_to "zoo"
  elsif current_human
    redirect_to "home"
  else
    # some unauthorised access alert
  end
end

據我了解,我需要將這種代碼放入 Rails 4 應用程序中的每個控制器中。 那是對的嗎?

我的主要問題是:有沒有更好的方法來做到這一點? 我想在application_controller.rb中放置一個方法,該方法為訪問我的應用程序控制器的每種類型的啟用設計的用戶模型構建整個授權邏輯。 對於這種邏輯,那會是一個更好的地方嗎? 這是正確的方法嗎? 還是我需要重新啟動並使用不同的方法?

在發現 Rails 4 不支持 CanCan 后,我在嘗試找到用戶授權解決方案時遇到了同樣的問題。我選擇的選項是 Pundit。 它真的很靈活,而且效果很好。

https://github.com/elabs/pundit

基本上,您設置了一堆策略類來管理您的控制器操作的用戶授權。

一個posts_controller 將有一個類似於這樣的策略類:

class PostPolicy
  attr_reader :user, :post

  def initialize(user, post)
    @user = user
    @post = post
  end

  def update?
    user.admin?
  end
end

並且您將授權控制器中的更新操作:

def update
  @post = Post.find(params[:id])
  authorize @post
  if @post.update(post_params)
    redirect_to @post
  else
    render :edit
  end
end

因此,如果用戶不是管理員,則會引發錯誤。 Pundit 允許您挽救 ApplicationController 中被拒絕的授權,並允許您添加自定義代碼。 例如,您可以執行以下操作:

class ApplicationController < ActionController::Base
  protect_from_forgery
  include Pundit

  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

private

  def user_not_authorized
    if current_monkey
      redirect_to "zoo"
    elsif current_human
      redirect_to "home"
    else
      flash[:error] = "You are not authorized to perform this action."
      redirect_to request.headers["Referer"] || root_path
    end
  end
end

您還可以為同一策略類中的多個設計用戶配置策略。 例如,在 PostPolicy 類中,您可以檢查用戶的類型並基於此授予權限:

def index?
  return true if user.type == "Monkey"
end

就像 miahabdu 說的,首先認證(查看用戶是否存在),然后授權(查看用戶的權限)。

但是,您不必停止使用 devise,也不需要 Cancan。

這是在身份驗證后立即進行“授權”的簡單方法。

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_action :authenticate_user!
  before_action :check_access

  private

  def check_access
    if current_user.present?
      unless find_permission(current_user, 'code assigned for login access')
        sign_out current_user
        redirect_to new_user_session_path
      end
    end

  end

end

不要太find_permission是什么。 基本上current_user來自設計,而sign_out current_user正是這樣做的。 但是,在您注銷current_user之后,您需要將redirect_to new_user_session_pathredirect_to new_user_session_path ,假設User模型是您用於設計的。

現在,我對您的代碼所做的唯一小改動是使用 CaseElse 而不是 IfElse。

因此,要將您的代碼實現到我的示例中,我將對check_access方法執行此check_access

def check_access
  if current_user.present?
    unless find_permission(current_user, 'code assigned for login access')
      sign_out current_user
      redirect_to new_user_session_path
    end

    if current_admin
      redirect_to "admin_page"

    elsif current_monkey
      redirect_to "zoo"

    elsif current_human
      redirect_to "home"

    else
      sign_out current_user
      redirect_to new_user_session_path

    end

  end

end

最后,為什么要在開始時檢查注銷訪問權限? 它更快。 最后,您不必花費系統時間檢查所有權限,因為無論如何用戶都沒有登錄權限。

  • 首先,用戶是否存在? - 驗證
  • 第二,用戶是否有登錄? - 授權
  • 三、權限是什么? - 授權

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM