rails+devise+cancancan+rolify注册登录多角色权限管理
Mac环境
Ruby 2.4.1
Rails 5.1.2
进入正题,本章主要是解决多角色权限问题,使用 devise 、 cancancan 、rolify 。
注:所有 $ 开头的都是终端里输入的,其它都是项目里面的文档加入的。
1、先创建好新的项目
$ rails new demo
2、打开Gemfile,加入以下gem
gem 'devise' gem 'cancancan' gem 'rolify'
3、进入项目文件侠里
$ cd demo
4、安装刚刚加入的gem
$ bundle install
5、安装devise
$ rails g devise:install
6、打开config/environments/development.rb 文件,在里面输入
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
7、打开 config/routes.rb,在里面输入
root to: "home#index"
8、打开app/views/layouts/application.html.erb 文件,在<%= yield %>前面加入以下代码:
<p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p>
9、在终端输入以下代码:
$ rails g devise:views
10、现在添加一个提前routes.rb里提到的home目录和index文件,在终端执行以下代码:
$ rails g controller home index
11、在终端输入以下代码:
$ rails g devise user
12、创建一个list列表,这个list是用scaffold(脚手架)直接产生出来,在终端下输入以下代码:
$ rails g scaffold list name idcard phone
13、在终端下输入以下代码:
$ rails db:migrate
14、打开app/controllers/lists_controller.rb 和 app/controllers/home_controller.rb,把以下代码输入相应的位置:
before_action :authenticate_user!
注:这个是Devise的提供的方法,验证登录后才能打开这个list页面
15、增加一个注册登录的导航,按下方法操作,打开app/views/layouts/application.html.erb,在<%= yield %>前面输入以下代码:
<% if current_user %> <%= link_to('退出', destroy_user_session_path, :method => :delete) %> | <%= link_to('修改密码', edit_registration_path(:user)) %> <% else %> <%= link_to('注册', new_registration_path(:user)) %> | <%= link_to('登录', new_session_path(:user)) %> <% end %>
16、接下来集成cancancan、rolify
$ rails generate cancan:ability $ rails generate rolify Role User
17、打开db/migrate/20171217141406_rolify_create_roles.rb,在最后加上[5.1]这个参数,前面20171217141406这个时间戳与你的不一样。
class RolifyCreateRoles < ActiveRecord::Migration[5.1]
18、在终端下输入以下代码:
$ rails db:migrate
19、打开app/controllers/application_controller.rb,输入以下代码:
class ApplicationController < ActionController::Base protect_from_forgery with: :exception def after_sign_in_path_for(resource) if resource.is_a?(User) if User.count == 1 resource.add_role 'admin' end resource end root_path end end
注:以上代码是设置第一个注册用户id=1时为admin管理员,当id=2时就不是admin,当我注册第一个用户后我就把1改成2,admin改成user,那注第2个账号时就是user权限 ,待会user做一个比admin还低一级的权限。
20、打开app/models/ability.rb,输入以下代码:
class Ability include CanCan::Ability def initialize(user) if user.has_role? :admin #这里的admin权限等级最高,能增删改查。 can :manage, :all elsif user.has_role? :user #这里的user权限等级次于admin,能增改查,没有删除功能。 can :manage, :all cannot :destroy, :all #这里就是去掉删除功能。 else can :read, :all #else之后的用户只有只读功能。 end end end
注:上面图片内容截图于http://blog.xdite.net/posts/2012/07/30/cancan-rule-engine-authorization-based-library-3/
21、打开app/controllers/lists_controller.rb,增加以下代码:
class ListsController < ApplicationController load_and_authorize_resource #这个是cancancan全局权限验证的方法 before_action :authenticate_user! #这个是devise的登录验证方法
注:这里有 load_and_authorize_resource
22、打开app/controllers/application_controller.rb,增加以下代码:
rescue_from CanCan::AccessDenied do |exception| redirect_to lists_path , :alert => exception.message exception.action, exception.subject
end
注:如果权限认证失败,cancan会抛出一个CanCan::AccessDenied的异常,你可以在ApplicationController中捕获它来显示自己内容。这里引用了https://www.cnblogs.com/bendanchenzhicheng/archive/2011/09/05/2167451.html
23、打开app/views/layouts/application.html.erb,增加以下代码:
<!DOCTYPE html> <html> <head> <title>Demo</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <div class="container"> <div class="col-md-12"> <%= link_to '首页', root_path %> | <% if current_user %> Welcome come <%= current_user.email %> <%= link_to '退出', destroy_user_session_path, :method => :delete %> | <%= link_to '修改密码', edit_registration_path(:user) %> <% else %> <%= link_to '注册', new_registration_path(:user) %> | <%= link_to '登录', new_session_path(:user) %> <% end %> <p class="text-danger"><%= alert %></p> <%= yield %> </div> </div> </body> </html>
23、打开 app/views/home/index.html.erb,增加以下代码:
<h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <% if user_signed_in? %> <%= link_to "Lists", lists_path %> <% end %>
24、打开app/views/lists/index.html.erb,增加以下代码:
<h1>Lists</h1> <table class="table table-bordered"> <tr> <th>Name</th> <th>Idcard</th> <th>Phone</th> <% if can? :manage, @list %> <th colspan="3"></th> <% end %> </tr> <% @lists.each do |list| %> <tr> <td><%= list.name %></td> <td><%= list.idcard %></td> <td><%= list.phone %></td> <% if can? :manage, @list %> <td><%= link_to 'Show', list %></td> <td><%= link_to 'Edit', edit_list_path(list) %></td> <% if can? :destroy, @list %> <td><%= link_to 'Destroy', list, method: :delete, data: { confirm: 'Are you sure?' } %></td> <% end %> <% end %> </tr> <% end %> </table> <% if can? :create, @list %> <%= link_to 'New List', new_list_path %> <% end %>
25、按以上的操作基本实现了三角色权限管理,现在我们打开终端,在项目内,输入rails s,启动服务器,打开浏览器,输入http://localhost:3000,就正常显示一个Log in的页面。现在我们注册一个具有admin权限的账号;成功后,到回第19项操作,把1改成2,把admin改成user,保存,我们再注册一个具有user权限的账号,注册成功后,马上到回第19项操作,注释掉以下代码:
# def after_sign_in_path_for(resource) # if resource.is_a?(User) # if User.count == 2 # resource.add_role 'user' # end # resource # end # root_path # end
好了,我们现在有2个账号,一个是admin的,一个是user的。然后把上面这个功能注释后,以后注册的都是只有read功能的账号。
ok,完成。