Google App Engine用フレームワークKayのRESTfull APIの機能(RESTViewGroup)でアクセス制限を行う方法の続き。
前回までのまとめ。
- Google App Engine用フレームワークKayにはRESTViewGroupというRESTfull APIを簡単に実装するための機能が用意されています。
- RESTViewGroupでアクセス制限を行うにはauthorizeメソッドをオーバーライドします。
- authorizeメソッドで例外kay.exceptions.NotAuthorizedをraiseすることでアクセスを拒否できます。
- authorizeメソッドの引数operationをチェックすることで、処理内容を確認できます。
- operationがとる値は、OP_LIST, OP_SHOW, OP_CREATE, OP_UPDATE, OP_DELETEのいずれか。
authorizeメソッドの定義
from kay.generics import (OP_LIST, OP_SHOW, OP_CREATE, OP_UPDATE, OP_DELETE)
from kay.exceptions import NotAuthorized
class MyRESTViewGroup(RESTViewGroup):
models = ['myapp.models.MyModel']
def authorize(self, request, operation, obj=None, model_name=None,
prop_name=None):
'''アクセス制限
@param request: リクエスト
@param operation: 処理(OP_LIST, OP_SHOW, OP_CREATE, OP_UPDATE, OP_DELETE)
@param obj: 処理対象のオブジェクト(OP_SHOW, OP_UPDATE, OP_DELETEのときのみ)
@param model_name: モデル名
@param prop_name:
@raise e: アクセスを許可しないときは kay.exceptions.NotAuthorized を投げる
'''
return True
今回は、URLに付与したユーザー名とパスワードで認証する方法を紹介します。
その後、Basic認証による認証方法を紹介します。
次のようなURLによるアクセスで認証します。
http://~/rest/MyMode?user_name=ユーザー名&password=パスワード
URLに付与されたパターメータはrequest.value.get(パラメータ名)で取得することが出来ます。
user_name = request.values.get('user_name')
password=request.values.get('password'))
指定されたユーザー名とパスワードでログインできるかどうかを調べるには、kay.auth.login()を使用します。
from kay.auth import login
result = login(request, username=ユーザー名, password=パスワード)
# ログインに失敗したときはアクセスを認めない
if not result: raise NotAuthorized
ログインに成功した場合、request.userのis_adminやis_anonymous()で、権限を検証することが出来ます。
# 管理者権限がないときはアクセスを認めない
if not request.user.is_admin:
raise NotAuthorized
全体のソースコードは次のようになります。
myapp/urls.py
from kay.routing import (ViewGroup, Rule)
from kay.generics.rest import RESTViewGroup
class MyRESTViewGroup(RESTViewGroup):
models = ['myapp.models.MyModel']
def authorize(self, request, operation, obj=None, model_name=None,
prop_name=None):
'''アクセス制限
@param request: リクエスト
@param operation: 処理(OP_LIST, OP_SHOW, OP_CREATE, OP_UPDATE, OP_DELETE)
@param obj: 処理対象のオブジェクト(OP_SHOW, OP_UPDATE, OP_DELETEのときのみ)
@param model_name: モデル名
@param prop_name:
@raise e: アクセスを許可しないときは kay.exceptions.NotAuthorized を投げる
'''
from kay.auth import login
from kay.exceptions import NotAuthorized
# ログインできるか
result = login(request,
user_name=request.values.get('user_name'),
password=request.values.get('password'))
# ログインに失敗したときはアクセスを認めない
if not result: raise NotAuthorized
# 管理者権限がないときはアクセスを認めない
if not request.user.is_admin: raise NotAuthorized
return True
view_groups = [
MyRESTViewGroup(),
ViewGroup(
Rule('/', endpoint='index', view='myapp.views.index'),
)
]
開発サーバーでアクセスします。
http://localhost:8080/rest/MyModel?user_name=ユーザー名&password=パスワード
管理者権限を持つユーザーのユーザー名とパスワードでアクセスすれば表示されます。
次にユーザー名とパスワードをURLに付与するのではなく、Basic認証で送信するように変更します。
Google App EngineによるBasic認証は「Google App Engine でBasic認証を実装 改 – すぎゃーんメモ」を参考にさせていただきました。
ヘッダーの情報はrequest.headers.get(ヘッダ名)で取得することが出来ます。
auth_header = request.headers.get('Authorization')
if not auth_header: raise NotAuthorized
取得した情報からユーザー名とパスワードを取得します。
(scheme, base64str) = auth_header.split(' ')
if scheme != 'Basic': raise NotAuthorized
(username, password) = base64.b64decode(base64str).split(':')
後は先ほどと同じ。
result = login(request, user_name=username, password=password)
# ログインに失敗したときはアクセスを認めない
if not result: raise NotAuthorized
# 管理者権限がないときはアクセスを認めない
if not request.user.is_admin: raise NotAuthorized
全体のソースコードは次のようになります。
class MyRESTViewGroup(RESTViewGroup):
models = ['myapp.models.MyModel']
def authorize(self, request, operation, obj=None, model_name=None,
prop_name=None):
from kay.auth import login
from kay.exceptions import NotAuthorized
import base64
# ヘッダーから認証情報を取得する
auth_header = request.headers.get('Authorization')
if not auth_header: raise NotAuthorized
# 取得した情報からユーザー名とパスワードを取得する
(scheme, base64str) = auth_header.split(' ')
if scheme != 'Basic': raise NotAuthorized
(username, password) = base64.b64decode(base64str).split(':')
result = login(request, user_name=username, password=password)
# ログインに失敗したときはアクセスを認めない
if not result: raise NotAuthorized
# 管理者権限がないときはアクセスを認めない
if not request.user.is_admin: raise NotAuthorized
return True
動作を検証するためのテストコードです。
# -*- coding: utf-8 -*-
import urllib2
import base64
username = 'username'
password = 'password'
url = 'http://localhost:8080/rest/metadata'
base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
authheader = 'Basic %s' % base64string
req = urllib2.Request(url)
req.add_header("Authorization", authheader)
handle = urllib2.urlopen(req)
print handle.read()