Ruby on Rails
Autoryzacja za pomocą CanCan
Szukaj…
Wprowadzenie
CanCan to prosta strategia autoryzacji dla Railsów, która jest oddzielona od ról użytkowników. Wszystkie uprawnienia są przechowywane w jednym miejscu.
Uwagi
Przed użyciem CanCan nie zapomnij utworzyć Użytkowników, opracowując klejnot lub ręcznie. Aby uzyskać maksymalną funkcjonalność CanCan, utwórz użytkownika Admin.
Rozpoczęcie pracy z CanCan
CanCan to popularna biblioteka autoryzacji Ruby on Rails, która ogranicza dostęp użytkowników do określonych zasobów. Najnowszy klejnot (CanCanCan) jest kontynuacją martwego projektu CanCan .
Uprawnienia są zdefiniowane w klasie Ability
i mogą być używane z kontrolerów, widoków, pomocników lub dowolnego innego miejsca w kodzie.
Aby dodać obsługę autoryzacji do aplikacji, dodaj klejnot CanCanCan do Gemfile
:
gem 'cancancan'
Następnie zdefiniuj klasę umiejętności:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
end
end
Następnie sprawdź autoryzację za pomocą load_and_authorize_resource
aby załadować autoryzowane modele do kontrolera:
class ArticlesController < ApplicationController
load_and_authorize_resource
def show
# @article is already loaded and authorized
end
end
authorize!
sprawdzić autoryzację lub zgłosić wyjątek
def show
@article = Article.find(params[:id])
authorize! :read, @article
end
can?
aby sprawdzić, czy obiekt jest autoryzowany przeciwko określonej akcji w dowolnym miejscu kontrolerów, widoków lub pomocników
<% if can? :update, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
Uwaga: Zakłada się, że podpisany użytkownik jest udostępniany za pomocą metody current_user
.
Definiowanie umiejętności
Zdolności są definiowane w klasie Ability
za pomocą metod can
i cannot
. Rozważ następujący skomentowany przykład jako podstawowe odniesienie:
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
Obsługa dużej liczby umiejętności
Gdy liczba definicji umiejętności zacznie się powiększać, obsługa pliku umiejętności staje się coraz trudniejsza.
Pierwszą strategią radzenia sobie z tym problemem jest przeniesienie umiejętności na znaczące metody, zgodnie z tym przykładem:
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
Gdy klasa ta stanie się wystarczająco duża, możesz spróbować podzielić ją na różne klasy, aby sprostać różnym obowiązkom:
# 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
a następnie zdefiniuj te klasy jako:
# app/models/abilities/guest.rb
module Abilities
class Guest
include CanCan::Ability
def initialize(user)
# Abilities for anonymous visitors only
end
end
end
i tak dalej z Abilities::Authenticated
, Abilities::Admin
lub jakikolwiek inny.
Szybko przetestuj umiejętność
Jeśli chcesz szybko przetestować, czy klasa zdolności daje odpowiednie uprawnienia, możesz zainicjować zdolność w konsoli lub w innym kontekście z załadowanym środowiskiem szynowym, po prostu przekaż instancję użytkownika, aby przetestować:
test_ability = Ability.new(User.first)
test_ability.can?(:show, Post) #=> true
other_ability = Ability.new(RestrictedUser.first)
other_ability.cannot?(:show, Post) #=> true
Więcej informacji: https://github.com/ryanb/cancan/wiki/Testing-Abilities