12/08/2018, 10:48
Tìm hiểu về gem cancancan
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 ...
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