Ruby on Rails
Autorizzazione con CanCan
Ricerca…
introduzione
CanCan è una semplice strategia di autorizzazione per Rails disaccoppiata dai ruoli utente. Tutte le autorizzazioni sono archiviate in un'unica posizione.
Osservazioni
Prima di utilizzare CanCan, non dimenticare di creare utenti o inventare gem o manualmente. Per ottenere la massima funzionalità di CanCan, creare un utente amministratore.
Iniziare con CanCan
CanCan è una libreria di autorizzazione popolare per Ruby on Rails che limita l'accesso degli utenti a risorse specifiche. L'ultima gemma (CanCanCan) è la continuazione del progetto morto CanCan .
Le autorizzazioni sono definite nella classe Ability
e possono essere utilizzate da controller, viste, helper o qualsiasi altra posizione nel codice.
Per aggiungere il supporto di autorizzazione a un'app, aggiungi la gemma CanCanCan al Gemfile
:
gem 'cancancan'
Quindi definire la classe di abilità:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
end
end
Quindi verifica l'autorizzazione utilizzando load_and_authorize_resource
per caricare i modelli autorizzati nel controller:
class ArticlesController < ApplicationController
load_and_authorize_resource
def show
# @article is already loaded and authorized
end
end
authorize!
per verificare l'autorizzazione o sollevare un'eccezione
def show
@article = Article.find(params[:id])
authorize! :read, @article
end
can?
per verificare se un oggetto è autorizzato contro una determinata azione in qualsiasi punto dei controller, delle viste o degli helper
<% if can? :update, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
Nota: si presume che l'utente firmato sia fornito dal metodo current_user
.
Definire le abilità
Le abilità sono definite nella classe Ability
usando i metodi can
e cannot
. Considerare il seguente esempio commentato come riferimento di base:
class Ability
include CanCan::Ability
def initialize(user)
# for any visitor or user
can :read, Article
if user
if user.admin?
# admins can do any action on any model or action
can :manage, :all
else
# regular users can read all content
can :read, :all
# and edit, update and destroy their own user only
can [:edit, :destroy], User, id: user_id
# but cannot read hidden articles
cannot :read, Article, hidden: true
end
else
# only unlogged visitors can visit a sign_up page:
can :read, :sign_up
end
end
end
Gestire un gran numero di abilità
Una volta che il numero di definizioni di abilità inizia a crescere in numero, diventa sempre più difficile gestire il file Ability.
La prima strategia per gestire questi problemi è spostare le abilità in metodi significativi, come in questo esempio:
class Ability
include CanCan::Ability
def initialize(user)
anyone_abilities
if user
if user.admin?
admin_abilities
else
authenticated_abilities
end
else
guest_abilities
end
end
private
def anyone_abilities
# define abilities for everyone, both logged users and visitors
end
def guest_abilities
# define abilities for visitors only
end
def authenticated_abilities
# define abilities for logged users only
end
def admin_abilities
# define abilities for admins only
end
end
Una volta che questa classe è cresciuta abbastanza, puoi provare a suddividerla in classi diverse per gestire le diverse responsabilità come questa:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
self.merge Abilities::Everyone.new(user)
if user
if user.admin?
self.merge Abilities::Admin.new(user)
else
self.merge Abilities::Authenticated.new(user)
end
else
self.merge Abilities::Guest.new(user)
end
end
end
e quindi definire quelle classi come:
# app/models/abilities/guest.rb
module Abilities
class Guest
include CanCan::Ability
def initialize(user)
# Abilities for anonymous visitors only
end
end
end
e così via con Abilities::Authenticated
, Abilities::Admin
o qualsiasi altro.
Prova rapidamente un'abilità
Se desideri testare rapidamente se una classe di abilità fornisce le autorizzazioni corrette, puoi inizializzare un'abilità nella console o in un altro contesto con l'ambiente rails caricato, basta passare un'istanza utente per testarla:
test_ability = Ability.new(User.first)
test_ability.can?(:show, Post) #=> true
other_ability = Ability.new(RestrictedUser.first)
other_ability.cannot?(:show, Post) #=> true
Ulteriori informazioni: https://github.com/ryanb/cancan/wiki/Testing-Abilities