Tìm hiểu về gem cancancan
Bài đăng này đã không được cập nhật trong 9 năm
Nếu bạn xây dựng một ứng dụng với nhiều loại user và điều bạn lo lắng nhất chính là phân quyền cho các user của bạn. Một giải pháp hiệu quả cho bạn đó là sử dụng gem Cancancan
để phân quyền cho các user
Cancancan
là một thư viện phân quyền cho ruby on rails, nó hạn chế các tài nguyên mà một user được phép truy cập. Tất cả các quyền hạn được quy định ở một nơi duy nhất (là class Ability) và riêng biệt với controllers, views và database queries
1. Cài đặt
Với rails 3 và 4, bạn thêm vào Gemfile dòng sau, sau đó chạy lệnh bundle install
gem 'cancancan', '~> 1.10'
2. Bắt đầu với Cancancan
2.1. Định nghĩa Abilities:
Phân quyền User được định nghĩa trong class Ability. Cancan 1.5 gồm có 1 bộ tạo rails 3 và 4 để tạo ra class này
rails g cancan:ability
Trong rails 2.3, chỉ cần thêm một class mới trong app/models/ability.rb
với nội dung như sau
class Ability
include CanCan::Ability
def initialize(user)
end
end
Ví dụ
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
Các model người dùng hiện thời được cho vào phương thức initialize
, vì vậy việc phân quyền có thể được thay đổi dựa trên bất kỳ các thuộc tính của user
Phương thức can
:
Phương thức can
được sử dụng để định nghĩa việc phân quyền và yêu cầu 2 tham số. Đầu tiên là action mà bạn đang thiết lập phân quyền cho, thứ 2 là calss của đối tượng mà bạn muốn thiết lập action đó cho nó
can :update, Article
Bạn có thể đặt :manage
để đại diện cho bất kỳ hành động nào và :all
đại diện cho bất kỳ đối tượng nào
can :manage, Article # user can perform any action on the article
can :read, :all # user can read any object
can :manage, :all # user can perform any action on any object
Bạn có thể nhập 1 mảng các tham số. Ví dụ, user sẽ có khả năng update và destroy cả articles và comments
can [:update, :destroy], [Article, Comment]
2.2. Kiểm tra Ability và phân quyền:
Sau khi định nghĩa Ability
, bạn có thể sử dụng phương thức can?
và cannot?
trong view và controller để kiểm tra quyền của user cho action và object
<% if can? :update, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
Phương thức cannot?
thì đối lập với phương thức can?
Phương thức authorize!
trong controller sẽ đưa ra một ngoại lệ nếu user không có khả năng để thực hiện hành động đó
def show
@article = Article.find(params[:id])
authorize! :read, @article
end
Hay bạn có thể sử dụng phương thức load_and_authorize_resource
để cung cấp ủy quyền tự động cho tất cả các hành động trong RESTfull. Nó sẽ sử dụng bộ lọc trước để load tài nguyên vào một biến instance và cho phép nó mọi hành động
class ArticlesController < ApplicationController
load_and_authorize_resource
def show
# @article is already loaded and authorized
end
end
Strong Parameters:
khi sử dụng strong_parameters
hoặc Rails 4+, bạn có làm sạch đầu ra trước khi lưu bản ghi trong các action như :create
và :update
Ngoài ra, load_and_authorize_resource
có thể chọn lựa lấy param_method
để xác định một phương thức tùy ý trong controller để chạy
Bạn có thể liên kết lựa chọn param_method
với một ký tự tương ứng với tên của phương thức mà sẽ được gọi
class ArticlesController < ApplicationController
load_and_authorize_resource param_method: :my_sanitizer
def create
if @article.save
# hurray
else
render :new
end
end
private
def my_sanitizer
params.require(:article).permit(:name)
end
end
Bạn cũng có thể sử dung một string, nó sẽ được đánh giá trong khuôn khổ controller đang sử dụng instance_eval
và cần phải chứa code Ruby phù hợp
load_and_authorize_resource param_method: 'permitted_params.article'
Cuối cùng, nó có thể liên kết param_method
với một đối tượng Proc được gọi bởi controller như một đối số duy nhất
load_and_authorize_resource param_method: Proc.new { |c| c.params.require(:article).permit(:name) }
2.3. Xử lý các truy cập trái phép:
Nếu việc cấp phép user thất bại, một ngoại lệ CanCan::AccessDenied
sẽ được sinh ra. Bạn có thể bắt lấy và thay đổi hành vi của nó trong ApplicationController
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
end
2.4. Lock It Down:
Nếu bạn muốn đảm bảo chắc chắn việc cấp phép xẩy ra trên mọi action trong ứng dụng của bạn, hãy thêm vào check_authorization
vào ApplicationContronller
class ApplicationController < ActionController::Base
check_authorization
end
Điều này sẽ sinh ra một ngoại lệ nếu việc ủy quyền không được thực hiện trong một action. Nếu bạn muốn bỏ qua việc này thì thêm skip_authorization_check
vào một lớp con controller
Kết luận
Nhờ có gem Cancan mà việc phân quyền cho các user trở nên đơn giản và dễ dàng hơn rất nhiều, giúp ích rất nhiều cho ứng dụng của bạn. Kiến thức còn hạn hẹp và nhiều thiếu sót, rất mong sự góp ý của bạn đọc. Rất cảm ơn bạn đã theo dõi bài viết của tôi. Mong rằng nó sẽ giúp ích cho bạn đc phần nào đó. Xin chân thành cảm ơn!
tài liệu tham khảo: https://github.com/CanCanCommunity/cancancan
All rights reserved