【问题标题】:Rails Admin not authenticating with Cancancan or DeviseRails 管理员未使用 Cancancan 或 Devise 进行身份验证
【发布时间】:2019-04-22 02:14:44
【问题描述】:

我在配置中试过这个:

  ### Popular gems integration
  config.authenticate_with do
    warden.authenticate! scope: :user
  end
  config.current_user_method(&:current_user)

在这里,访问/admin 让我陷入了登录循环。我登录然后被重定向到登录页面。

我之前尝试过

class Ability
  include CanCan::Ability

  def initialize(user)
    # Define abilities for the passed in user here. For example:
    #
      user ||= User.new # guest user (not logged in)
      if user.admin?

在 Rails 管理配置中使用 CanCanCan 身份验证。这导致用户始终为零。即使我投入了

config.current_user_method(&:current_user)

如何解决此问题以验证是否为管理员?

编辑:在会话控制器中

      if user.admin
        redirect_to rails_admin_url
      else
        render json: user
      end

然后我卡在重定向回登录页面。

路线:

Rails.application.routes.draw do
  mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
  devise_for :users, controllers: { sessions: :sessions },
                      path_names: { sign_in: :login }
... then many resources lines

编辑:

会话控制器:

class SessionsController < Devise::SessionsController
  protect_from_forgery with: :null_session

  def create
    user = User.find_by_email(sign_in_params[:email])
    puts sign_in_params
    if user && user.valid_password?(sign_in_params[:password])
      user.generate_auth_token
      user.save
      if user.admin
        redirect_to rails_admin_url
      else
        render json: user
      end
    else
      render json: { errors: { 'email or password' => ['is invalid'] } }, status: :unprocessable_entity
    end
  end
end

Rails 管理员配置,试试这个:

  ### Popular gems integration
  config.authenticate_with do
    redirect_to merchants_path unless current_user.admin?
  end
  config.current_user_method(&:current_user)

在应用控制器中:

def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
  helper_method :current_user

试过了,current_user 是 nil。

【问题讨论】:

  • 你能显示你的config/routes.rb 吗?范围取决于您在config/routes.rb 中定义的内容
  • 所以,设置 current_user 不起作用,但在会话控制器中显式设置 session[:user_id] 然后 config.authenticate_with 做 redirect_tocommerce_path 除非 User.find(session[:user_id]).admin?以 rails admin config 结束

标签: ruby-on-rails devise rails-admin cancancan


【解决方案1】:

重定向的控制器逻辑

Guillermo Siliceo Trueba 的解决方案不适用于您的 Users::SessionsController#create 操作,因为您没有通过关键字 super 调用 the parent class create action

Devise::SessionsController 类中的方法create 将在最后一行运行respond_with,使用locationafter_sign_in_path_for(resource) 返回的值

class Devise::SessionsController < DeviseController
  # POST /resource/sign_in
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message!(:notice, :signed_in)
    sign_in(resource_name, resource)
    yield resource if block_given?
    respond_with resource, location: after_sign_in_path_for(resource)
  end
end

我在我的Users::SessionsController 中使用此解决方案来处理htmljson 请求,您可以实现相同的。

如果控制器接收到格式为.jsonrequest,则执行format.json do .. end之间的代码,如果requestformat.html到达,则调用父方法(我涵盖了所有场景)。

Rails 路由器从 url 末尾附加的 .json.html 识别请求格式(例如 GET https://localhost:3000/users.json

class Users::SessionsController < Devise::SessionsController
  def create
    respond_to do |format|
      format.json do 
        self.resource = warden.authenticate!(scope: resource_name, recall: "#{controller_path}#new")
        render status: 200, json: resource
      end
      format.html do 
        super
      end
    end
  end
end

html 请求将被路由到 to the super create action。您只需要将父级的def after_sign_in_path_for(resource) 方法重写为I am doing in my ApplicationController

if resource.admin 然后只是 return rails_admin_url 从此方法中跳过其他行,否则按照正常行为调用super#after_sign_in_path_for(resource)

def after_sign_in_path_for(resource)
  return rails_admin_url if resource.admin
  super
end

身份验证错误消息

warned.authenticate! 将在self.resource.errors 中保存错误消息。您只需要使用json_response[:error] 在您的设备上显示错误并在您的前端处理响应。

我将它们呈现在SignInScreen Component

令牌认证

user.generate_auth_token
user.save

我使用simple_token_authentication for devise,它也允许您使用regenerate the token every time the user signs in

您只需安装 gem 并添加 acts_as_token_authenticatable inside your user model

class User < ApplicationRecord
   acts_as_token_authenticable
end

您传递标头X-User-EmailX-User-Token 以及in their guide 解释的相应值。

其他alternatives to simple_token_authentication

【讨论】:

    【解决方案2】:

    您可能需要在 ApplicationController 上定义 after_sign_in_path_for 方法

    默认情况下,它首先尝试在会话中找到有效的 resource_return_to 键,然后回退到 resource_root_path,否则使用根路径。对于用户范围,您可以通过以下方式定义默认 url:

    get '/users' => 'users#index', as: :user_root # creates user_root_path
    
    namespace :user do
      root 'users#index' # creates user_root_path
    end
    

    如果未定义资源根路径,则使用 root_path。不过如果这个默认还不够用,可以自定义一下,例如:

    def after_sign_in_path_for(resource)
      stored_location_for(resource) ||
        if resource.is_a?(User) && resource.can_publish?
          publisher_url
        else
          super
        end
    end
    

    【讨论】:

    • 嘿,我发现问题出在我的 Sessions 控制器中,它只是返回 JSON。我试过做==请看编辑
    猜你喜欢
    • 2011-09-18
    • 2014-01-04
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    相关资源
    最近更新 更多