Pyramidのチュートリアルをやってみる④ 〜 wikiアプリケーションの設計(認証の追加)
Pyramidのチュートリアルをやってみる③ 〜 wikiアプリケーションの設計(ビューの定義) - [[ともっくす alloc] init]の続き.
今回は,前回までに作ったwikiアプリケーションに認証を追加するところまで.
今のままだと,誰でも記事を編集できたりするからね.
で,チュートリアルも今回で終わりかと思う.
やるとしても,しばらく先かなと.
アクセス制御
ユーザとグループの追加
tutorialディレクトリ内(views.pyとかと同じ階層)にsecurity.pyを作成し,以下を記述する.
USERS = {'editor': 'editor', 'viewer': 'viewer'} GROUPS = {'editor':['group:editors']} def groupfinder(userid, request): if userid in USERS: return GROUPS.get(userid, [])
groupfinderは,指定されたuseridが登録されているかを確認し,その権限を返す.
例えば,useridがeditorのユーザは,group:editorという権限を持つ.
本来は,これらのデータはDB等で管理されるが,今回はチュートリアルなので,こんな感じの管理方法になっている.
ACLの追加
models.pyに以下のfrom-import文を追加.
from pyramid.security import ( Allow, Everyone, )
そして,以下のクラスも追加.
class RootFactory(object): __acl__ = [(Allow, Everyone, 'view'), (Allow, 'group:editors', 'edit')] def __init__(self, request): pass
そしてそして,__init__.pyのConfiguratorコンストラクタにroot_factoryパラメータを追加する.
config = Configurator(settings=settings, root_factory='tutorial.models.RootFactory')
ACLはAccess Control Listの略.
それを__acl__で定義している.
簡単に言うと,全てのユーザ(Everyone)に'view'の権限を与え,'group:editor'であるユーザに'edit'の権限を与えるというもの.
認証と認可のポリシーを追加
__init__.pyに以下のfrom-import文を追加.
from pyramid.authentication import AuthTktAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy from tutorial.security import groupfinder
そして,Configuratorコンストラクタの前後に以下を追加する.
authn_policy = AuthTktAuthenticationPolicy('sosecret', callback=groupfinder, hashalg='sha512') authz_policy = ACLAuthorizationPolicy() config = Configurator(settings=settings, root_factory='tutorial.models.RootFactory') config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy)
パーミッション宣言を追加
@view_configデコレータにパーミッションを追加する.
add_page()とedit_page()のパーミッションはedit,つまり,edit権限のあるユーザのみ
@view_config(route_name='add_page', renderer='templates/edit.pt', permission='edit') @view_config(route_name='edit_page', renderer='templates/edit.pt', permission='edit')
view_wiki()とview_page()のパーミッションはview,つまり,view権限のあるユーザのみ(全ユーザ)
@view_config(route_name='view_wiki', permission='view') @view_config(route_name='view_page', renderer='templates/view.pt', permission='view')
ログインとログアウト
routeの追加
__init__.pyに以下のrouteを追加する.
config.add_route('login', '/login') config.add_route('logout', '/logout')
ビューの追加
views.pyのfrom-import文で,以下のように編集したり追加したり.
from pyramid.view import ( view_config, forbidden_view_config, ) from pyramid.security import ( remember, forget, ) from .security import USERS
で,以下を追加.
@view_config(route_name='login', renderer='templates/login.pt') @forbidden_view_config(renderer='templates/login.pt') def login(request): login_url = request.route_url('login') referrer = request.url if referrer == login_url: referrer = '/' came_from = request.params.get('came_from', referrer) message = '' login = '' password = '' if 'form.submitted' in request.params: login = request.params['login'] password = request.params['password'] if USERS.get(login) == password: headers = remember(request, login) return HTTPFound(location = came_from, headers = headers) message = 'Failed login' return dict( message = message, url = request.application_url + '/login', came_from = came_from, login = login, password = password, ) @view_config(route_name='logout') def logout(request): headers = forget(request) return HTTPFound(location = request.route_url('view_wiki'), headers = headers)
ここによって,
@forbidden_view_config(renderer='templates/login.pt')
ユーザがログインせずにページの追加や編集をしようとすると,ログインページに飛ばされる.
テンプレートの追加
templatesディレクトリにlogin.ptを作成し,内容を以下のようにする.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> <title>Login - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> <![endif]--> </head> <body> <div id="wrap"> <div id="top-small"> <div class="top-small align-center"> <div> <img width="220" height="50" alt="pyramid" src="${request.static_url('tutorial:static/pyramid-small.png')}" /> </div> </div> </div> <div id="middle"> <div class="middle align-right"> <div id="left" class="app-welcome align-left"> <b>Login</b><br/> <span tal:replace="message"/> </div> <div id="right" class="app-welcome align-right"></div> </div> </div> <div id="bottom"> <div class="bottom"> <form action="${url}" method="post"> <input type="hidden" name="came_from" value="${came_from}"/> <input type="text" name="login" value="${login}"/><br/> <input type="password" name="password" value="${password}"/><br/> <input type="submit" name="form.submitted" value="Log In"/> </form> </div> </div> </div> <div id="footer"> <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> </div> </body> </html>
logged_inフラグ
views.pyのfrom-import文を以下のように変更.
from pyramid.security import ( remember, forget, authenticated_userid, )
view_page(),edit_page(),add_page()のreturn文のdict(〜)に,以下を追加する.
return dict(〜〜〜, logged_in = authenticated_userid(request))
Logoutリンクの追加
edit.ptとview.ptを以下のように変更する.divタグの内側に追加.
〜 <div id="right" class="app-welcome align-right"> <span tal:condition="logged_in"> <a href="${request.application_url}/logout">Logout</a> </span> </div> 〜
アプリケーションの起動
これで,認証機能を追加できたので,アプリケーションを起動してみる.
$ pserve development.ini --reload Starting subprocess with file monitor Starting server in PID 4044. serving on http://0.0.0.0:6543
で,起動して,http://localhost:6543/FrontPageにアクセス.
(別にルートにアクセスでいいんだけど)
「Edit this page」をクリックしてみると,
URL自体はhttp://localhost:6543/FrontPage/edit_pageなのに,loginページに飛ばされる.
で,ユーザ名をeditor,パスワードをeditorと入力する.
loginボタンをクリックすると,しっかりと,FrontPageの編集ページにアクセスできる.
ここで,デバッグツールバーのHTTP Headersを見てみると,Cookieにauthトークンが追加されていることがわかる.
で,ログインしたので,FrontPageに戻ると,しっかりと右上にlogoutリンクができている.
簡単に,認証機能付きの簡易Wikipediaアプリケーションができた!
今回はこんな感じで終わり.
チュートリアルには,テストの追加とアプリケーションの配布という項目があるが,これらをやるかは未定.
次 > 未定
前 > Pyramidのチュートリアルをやってみる③ 〜 wikiアプリケーションの設計(ビューの定義) - [[ともっくす alloc] init]