Ruby on Rails给定用户角色的ERR_TOO_MANY_REDIRECTS错误

时间:2016-07-23 05:50:08

标签: ruby-on-rails ruby

我是Ruby on Rails的初学者,这是由某人开发的ruby on rails。

有两种类型的用户:注册用户"用户"角色和注册用户" admin"作用。

如果用户的角色="用户",则会发生太多重定向,但如果用户是" admin"则不会发生此重定向。我还没弄明白为什么。

首先,如果用户是管理员,我会在日志中得到这个:

Started GET "/" for ::1 at 2016-07-22 18:18:17 -0700
Processing by ProductsController#home as HTML
  ^[[1m^[[35mUser Load (0.1ms)^[[0m  SELECT  "users".* FROM "users" WHERE "users"."id" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["id", 11]]
controller_path: products
resource: product
method: product_params
after the parms setting => ${params}
Debugging in the Ability.rb...
User: #<User:0x007fe6d7f0f670>
user is admin
  ^[[1m^[[36mProduct Load (0.3ms)^[[0m  ^[[1mSELECT "products".* FROM "products"^[[0m
  ^[[1m^[[35mVersion Load (1.1ms)^[[0m  SELECT "versions".* FROM "versions"
  ^[[1m^[[36mReltype Load (1.0ms)^[[0m  ^[[1mSELECT "reltypes".* FROM "reltypes"^[[0m

以及更多SQL语句;我希望简化这一点,但这是一个不同的问题和另一个学习机会。

如果用户是普通用户,则&#34;重定向&#34;将在用户成为普通用户后立即发生

Started GET "/" for ::1 at 2016-07-22 18:25:23 -0700
Processing by ProductsController#home as HTML
  ^[[1m^[[36mUser Load (0.1ms)^[[0m  ^[[1mSELECT  "users".* FROM "users" WHERE "users"."id" = ?  ORDER BY "users"."id" ASC LIMIT 1^[[0m  [["id", 11]]
controller_path: products
resource: product
method: product_params
after the parms setting => ${params}
Debugging in the Ability.rb...
User: #<User:0x007fe6d13dca88>
user is regular user
Redirected to http://localhost:3000/
Completed 302 Found in 6ms (ActiveRecord: 0.1ms)


Started GET "/" for ::1 at 2016-07-22 18:25:23 -0700
Processing by ProductsController#home as HTML
  ^[[1m^[[35mUser Load (0.1ms)^[[0m  SELECT  "users".* FROM "users" WHERE "users"."id" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["id", 11]]
controller_path: products
resource: product
method: product_params
...repeat... for many more

我的猜测是着陆页试图提取所有数据以供在此页面中使用,并且每个SQL都会触发重定向......但首先,我想找到为什么它会对具有角色用户的用户产生影响与角色管理员。我稍后会担心优化。任何帮助将不胜感激。

这是config / routes.rb

Rails.application.routes.draw do
  resources :groupings
  resources :platforms
  resources :versions
  resources :reltypes
  resources :products

  # Devise stuff
  devise_for :users
  devise_scope :user do
    get '/login' => 'devise/sessions#new'
    get '/logout' => 'devise/sessions#destroy'
  end

  resources :users, :controller => "users"
  unauthenticated :user do
    resources :products, only: [:index, :show]
    resources :versions, only: [:index, :show]
    resources :reltypes, only: [:index, :show]
    resources :platforms, only: [:index, :show]
    resources :groupings, only: [:index, :show]
  end

  # You can have the root of your site routed with "root"
  root to: 'products#home'

  namespace :api, :defaults => {:format => :json} do
    resources :platforms
    resources :versions
    resources :reltypes
    resources :products
    resources :groupings
  end
end

接下来是controllers / application.rb

class ApplicationController < ActionController::Base
  # include DeviseTokenAuth::Concerns::SetUserByToken
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  # Devise: redirect to login page if user not logged in
  before_action :authenticate_user!

  before_filter do
    resource = controller_path.singularize.to_sym
    method = "#{resource}_params"
    Rails.logger.debug("controller_path: #{controller_path}")
    Rails.logger.debug("resource: #{resource}")
    Rails.logger.debug("method: #{method}")

    params[resource] &&= send(method) if respond_to?(method, true)
  end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:email, :password, :password_confirmation, roles: [])}
  end

  # CanCan: if user authorization fails, catch and modify
  check_authorization :unless => :devise_controller?

  rescue_from CanCan::AccessDenied do |exception|
    redirect_to root_url, :alert => exception.message
  end
end

这是models / user.rb

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :trackable, :validatable

  before_save :default_values

  def default_values
  #    self.role ||= 'user'
    self.role = "user"
  end

  def is?(requested_role)
    self.role == requested_role
  end
end

最后,我找到了这个models / activity.rb(我试着在这里放一些调试语句:

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)
    Rails.logger.debug("Debugging in the Ability.rb...")
    Rails.logger.debug("User: #{user}")

    if user.is? "admin"
      Rails.logger.debug("user is admin")
      can :manage, :all
    else
      Rails.logger.debug("user is regular user")
      can :read, :all
    end
  end
end

添加了controllers / products_controller.rb(由Sri Vishnu Totakura建议)。我跳过了更新/破坏的代码只是为了节省一点空间。

class ProductsController < ApplicationController
  load_and_authorize_resource #for CanCan

  before_action :set_product, only: [:show, :edit, :update, :destroy]

  # GET /products
  # GET /products.json
  def index
    @products = Product.all
  end

  def home
    @products = Product.all
    @versions = Version.all
    @platforms = Platform.all
    @reltypes = Reltype.all
    @prevrels = Prevrel.all
  end

  # GET /products/1
  # GET /products/1.json
  def show
  end

  # GET /products/new
  def new
    # puts "params for new: "
    # puts params
    @product = Product.new
  end

  # GET /products/1/edit
  def edit
  end

  # POST /products
  # POST /products.json
  def create
    puts "params for create: "
    puts params
    @product = Product.new(product_params)

    respond_to do |format|
      if @product.save
        format.html { redirect_to @product, notice: 'Product was successfully created.' }
        format.json { render :show, status: :created, location: @product }
      else
        format.html { render :new }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
     ...
  end

  def destroy
     ...
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_product
      @product = Product.find(params[:id])
      @versions = @product.versions
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def product_params
      params.require(:product).permit(:name)
    end
end

2 个答案:

答案 0 :(得分:1)

问题似乎在这里:

rescue_from CanCan::AccessDenied do |exception|
  redirect_to root_url, :alert => exception.message
end

由于某种原因,当您不是管理员时,会引发该异常,并且当您重定向到ProductsController#home

时,您会陷入循环

我没有看到您的产品控制器代码,但问题应该存在。让我知道。

答案 1 :(得分:0)

由于我无法发表评论或赞成Paulo的答案,因此我将此处留给所有遇到类似问题的人。

他的回答让我在我的控制器中更好地了解导致无限重定向,特别是触发的动作并最终解决了这个问题。

我也在使用devise/cancancan

具体来说,我有companies_controller.rb

此外,在before_action中我有类似下面的内容

before_action :set_company, only: :show

并且set_company操作是这个

def set_company
   ...
   authorize! params[:action].to_sym, @company || Company
end

我一删除授权!调用重定向循环停止。 我还没有想到是什么导致了循环,因为我的用户角色似乎很好,但这绝对是原因。