使用before_action的Rails授权体系结构

时间:2014-07-29 21:30:02

标签: ruby-on-rails session cookies authorization before-filter

我是Ruby和Rails的新手,所以我正在尝试做一些其他语言可能很容易的事情,但我无法在Rails中处理它:

我在数据库中设计了几个与每个控制器和操作名称匹配的表。这样,如果我想为用户管理特殊权限,我只需对数据库中正确的控制器执行适当的操作,并使用方法check_permissions,我知道用户是否可以执行操作或重定向到标准的“禁止”页面。

例如,这是我的用户CRUD的代码:

首先,我在应用程序控制器中创建了一个check_permissions方法,该方法抓取当前操作,用户和控制器,并检查对数据库的授权权限:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  include SessionsHelper

  def self.check_permissions 
    remember_token = User.digest(cookies[:remember_token]) # encripto el token para poder buscarlo en la DB, ya que ahi se guarda encriptado.
    @current_user ||= User.find_by(remember_token: remember_token)

    redirect_to signin_path if (@current_user == nil) or (User.find_by_sql("select * from view_userpermissions where user_id = #{@current_user.id} and pagecontroller='#{self.controller_name}' and accion='#{self.action}' ").count < 1)
  end
  ...
  ...

然后在每个控制器中,我使用before_action :check_permissions过滤器重定向用户,以防无权访问所需内容:

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
  before_action self.comprobar_permisos 

  def index
    @users = User.paginate(page: params[:page])
  end
  ...
  ...

代码流似乎工作得很好,但问题是在调用before_action过滤器时无法识别rails cookies hash。

我也尝试过使用会话,但发生的情况完全一样。

我想到的第一件事是,在Rails架构中,当执行过滤器时,会话或cookie哈希都没有实例化,然后当应用程序控制器尝试访问它们时,会显示错误:

Routing Error

undefined local variable or method `cookies' for UsersController:Class

Rails.root: C:/Users/daniel.tenzi/proyectos/MicroEstudio

Application Trace | Framework Trace | Full Trace 
    app/controllers/application_controller.rb:11:in `check_permissions'
    app/controllers/users_controller.rb:3:in `'
    app/controllers/users_controller.rb:1:in `'

Routes 

Routes match in priority from top to bottom 


Helper

HTTP Verb

Path

Controller#Action


Path / Url 

pagecontrollers_path  GET  /pagecontrollers(.:format)  pagecontrollers#index  
 POST  /pagecontrollers(.:format)  pagecontrollers#create  
new_pagecontroller_path  GET  /pagecontrollers/new(.:format)  pagecontrollers#new  
edit_pagecontroller_path  GET  /pagecontrollers/:id/edit(.:format)  pagecontrollers#edit  
pagecontroller_path  GET  /pagecontrollers/:id(.:format)  pagecontrollers#show  
 PATCH  /pagecontrollers/:id(.:format)  pagecontrollers#update  
 PUT  /pagecontrollers/:id(.:format)  pagecontrollers#update  
 DELETE  /pagecontrollers/:id(.:format)  pagecontrollers#destroy  
permissions_path  GET  /permissions(.:format)  permissions#index  
 POST  /permissions(.:format)  permissions#create  
new_permission_path  GET  /permissions/new(.:format)  permissions#new  
edit_permission_path  GET  /permissions/:id/edit(.:format)  permissions#edit  
permission_path  GET  /permissions/:id(.:format)  permissions#show  
 PATCH  /permissions/:id(.:format)  permissions#update  
 PUT  /permissions/:id(.:format)  permissions#update  
 DELETE  /permissions/:id(.:format)  permissions#destroy  
groups_path  GET  /groups(.:format)  groups#index  
 POST  /groups(.:format)  groups#create  
new_group_path  GET  /groups/new(.:format)  groups#new  
edit_group_path  GET  /groups/:id/edit(.:format)  groups#edit  
group_path  GET  /groups/:id(.:format)  groups#show  
 PATCH  /groups/:id(.:format)  groups#update  
 PUT  /groups/:id(.:format)  groups#update  
 DELETE  /groups/:id(.:format)  groups#destroy  
users_path  GET  /users(.:format)  users#index  
 POST  /users(.:format)  users#create  
new_user_path  GET  /users/new(.:format)  users#new  
edit_user_path  GET  /users/:id/edit(.:format)  users#edit  
user_path  GET  /users/:id(.:format)  users#show  
 PATCH  /users/:id(.:format)  users#update  
 PUT  /users/:id(.:format)  users#update  
 DELETE  /users/:id(.:format)  users#destroy  
empresas_path  GET  /empresas(.:format)  empresas#index  
 POST  /empresas(.:format)  empresas#create  
new_empresa_path  GET  /empresas/new(.:format)  empresas#new  
edit_empresa_path  GET  /empresas/:id/edit(.:format)  empresas#edit  
empresa_path  GET  /empresas/:id(.:format)  empresas#show  
 PATCH  /empresas/:id(.:format)  empresas#update  
 PUT  /empresas/:id(.:format)  empresas#update  
 DELETE  /empresas/:id(.:format)  empresas#destroy  
sessions_path  POST  /sessions(.:format)  sessions#create  
new_session_path  GET  /sessions/new(.:format)  sessions#new  
session_path  DELETE  /sessions/:id(.:format)  sessions#destroy  
root_path  GET  /  users#index  
signup_path  GET  /signup(.:format)  users#new  
signin_path  GET  /signin(.:format)  sessions#new  
signout_path  DELETE  /signout(.:format)  sessions#destroy  

但如果我的猜测是真的,为什么Rails会说routing error

我被困在这里至少一周试图找到任何可以帮助我前进但没有运气的东西。

我做错了什么?任何帮助将受到高度赞赏!

PS:我见过像Cancan这样的auth框架,但是不想使用任何一种,这应该更容易,更灵活。

谢谢!

1 个答案:

答案 0 :(得分:0)

您在课堂上调用Cookie,而不是实例。这是因为您的方法定义为def self.xxx

试试这个:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  include SessionsHelper

  def check_permissions 
    ...

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
  before_action :check_permissions 

  ...

您试图将before_action设置为类方法的结果。看一下这个方法,不是一个好主意 - 它是重定向而不是生成一个符号(before_action期望转换为实例方法名称)。此外,正如您所发现的那样,您无法访问课堂范围内的会话,请求,Cookie等。

另一方面,你不应该使用&#39;或&#39;用于条件操作,仅用于程序流控制。例如:

if a == 1 || b == 1 # good
if a == 1 or b == 1 # bad

thing = Thing.find(id) and thing.save # good
thing = Thing.find(id) && thing.save # bad

&#39;或&#39;和&#39;和&#39;优先级低于您的预期,因此可能会破坏您的条件。