Catalyst::Manual::Tutorial::06_Authorization
学习笔记 (2010-8-27 星期五)-- 用户权限管理
文章来源:
概述:
本章会讲述基于角色的用户权限管理,描述了如何在 TT 模板及 controller action 中使用角色控制。前半部分将基本的权限管理原则;后半部分讲述如何将权限管理代码移入到 model 中,从而可以简化管理。
本章的例子程序可以从 一章中描述的地址找到。
本章学习基本的 catalyst 的权限管理知识。
编辑 lib/MyApp.pm ,添加 Authorization::Roles :
# Load plugins use Catalyst qw/ -Debug ConfigLoader Static::Simple
StackTrace Authentication Authorization::Roles Session Session::Store::FastMmap Session::State::Cookie /;
|
同样修改 Makefile.PL ,添加:
requires 'Catalyst::Plugin::Authorization::Roles';
|
Add Role-Specific Logic to the "Book List" Template
编辑 root/src/books/list.tt2
,底部添加:
... <p>Hello [% c.user.username %], you have the following roles:</p> <ul> [% # Dump list of roles -%] [% FOR role = c.user.roles %]<li>[% role %]</li>[% END %] </ul> <p> [% # Add some simple role-specific logic to template %] [% # Use $c->check_user_roles() to check authz -%] [% IF c.check_user_roles('user') %] [% # Give normal users a link for 'logout' %]
<a href="[% c.uri_for('/logout') %]">User Logout</a> [% END %] [% # Can also use $c->user->check_roles() to check authz -%] [% IF c.check_user_roles('admin') %] [% # Give admin users a link for 'create' %] <a href="[% c.uri_for(c.controller.action_for('form_create')) %]">Admin Create</a> [% END %] </p>
|
Limit Books::add to 'admin' Users
通过 TT 模板简单控制浏览器,会导致一些安全问题,比如用户直接通过 url 调用 action ,我们接下来进行功能包裹,加强权限约束。
实例,我们约束 "formless create" 功能只能管理员使用,编辑 lib/MyApp/Controller/Books.pm 文件,修改 url_create :
sub url_create :Chained('base') :PathPart('url_create') :Args(3) { # In addition to self & context, get the title, rating & author_id args # from the URL. Note that Catalyst automatically puts extra information # after the "// my ($self, $c, $title, $rating, $author_id) = @_; # Check the user's roles
if ($c->check_user_roles('admin')) { # Call create() on the book model object. Pass the table # columns/field values we want to set as hash values my $book = $c->model('DB::Book')->create({ title => $title, rating => $rating });
# Add a record to the join table for this book, mapping to # appropriate author $book->add_to_book_authors({author_id => $author_id}); # Note: Above is a shortcut for this: # $book->create_related('book_authors', {author_id => $author_id}); # Assign the Book object to the stash and set template $c->stash(book => $book, template => 'books/create_done.tt2'); } else { # Provide very simple feedback to the user. $c->response->body('Unauthorized!'); } }
|
我们简单的将程序逻辑放到 check_user_roles 的 if 语句中,如果用户没有权限,将得到信息"Unauthorized!"。
提示:如果你想保存原始的 url_create ,可以先复制,再使用 pod 语法 =begin ,=end 进行注释。
Try Out Authentication And Authorization
$ script/myapp_server.pl -r
|
访问 ,会进入到登录界面(如果已登录就退出)。使用用户名 test01、 test02,密码 mypass ,注意观察页面 "Book List" 下的 role 信息。
你是用 test01 就可以正常访问 "url_create" ,使用 test02 会看到验证失败信息。
ENABLE MODEL-BASED AUTHORIZATION
上述权限控制浅显易懂,可未免不够清晰简洁,扩展性也不好。大部分 MVC 框架的目标,都是要是 controller 和 view 尽可能的简洁,尽可能的将业务逻辑放入 model 当中。
举个例子,让我给 Books.pm 结果类添加一个方法,用来检查一个用户是否有权限删除一本书。编辑 lib/MyApp/Schema/Result/Book.pm ,添加如下方法(要添加在 "DO NOT MODIFY ...
" 这一行下面):
sub delete_allowed_by { my ($self, $user) = @_; # Only allow delete if user has 'admin' role
return $user->has_role('admin'); }
|
这里我们在 user object 上调用 has_role 方法,我们就可以将这个方法添加到结果类中。编辑 lib/MyApp/Schema/Result/User.pm ,添加如下方法(注意在 "DO NOT MODIFY ...
" 后面):
use Perl6::Junction qw/any/; sub has_role { my ($self, $role) = @_; # Does this user posses the required role? return any(map { $_->role } $self->roles) eq $role; }
|
现在我们需要往 controller 里添加一些增强功能。编辑 lib/MyApp/Controller/Books.pm 文件,修改 delete 方法如下:
sub delete :Chained('object') :PathPart('delete') :Args(0) { my ($self, $c) = @_; # Check permissions $c->detach('/error_noperms') unless $c->stash->{object}->delete_allowed_by($c->user->get_object); # Use the book object saved by 'object' and delete it along # with related 'book_authors' entries $c->stash->{object}->delete; # Use 'flash' to save information across requests until it's read $c->flash->{status_msg} = "Book deleted"; # Redirect the user back to the list page $c->response->redirect($c->uri_for($self->action_for('list'))); }
|
这里,如果用户缺少适当权限会 detach 到错误信息页面。这里需要添加 '/error_noperms' action ,编辑 lib/MyApp/Controller/Root.pm ,添加:
sub error_noperms :Chained('/') :PathPart('error_noperms') :Args(0) { my ($self, $c) = @_; $c->stash(template => 'error_noperms.tt2'); }
|
然后添加模板文件,编辑 root/src/error_noperms.tt2:
<span class="error">Permission Denied</span>
|
用 test01 登录,用 url_create 创建几本书:
现在,以 test01 登录,可以点击 "Delete" 删除书目,操作正常,并得到 "Book deleted" 信息。退出,用 test02 登录,执行同样动作,你会得到 "Permission Denied" 信息。说明权限控制生效了。
本章结束
阅读(1117) | 评论(0) | 转发(2) |