Вот довольно солидная реализация, которую я придумал
В результате поиска я обнаружил множество небрежных / неполных реализаций BasicAuth для GAE в Интернете. В результате я написал свой собственный. Это самый лучший / самый простой подход, который мне удалось придумать.
Я считаю хорошей практикой сохранять обработчики запросов как можно более тонкими. Чтобы сократить количество шаблонов и копипаст в самих обработчиках, я решил реализовать аутентификацию в качестве декоратора. Чтобы использовать его, просто присоедините декоратор к методам обработчика get / post / put / delete.
Например:
from decorators import basic_auth
class Handler(webapp2.RequestHandler):
@basic_auth
def get(self):
# load your page here
Затем добавьте декоратор в decorators.py:
import base64
import os
from webapp2_extras import security
import yaml
def basic_auth(func):
def callf(webappRequest, *args, **kwargs):
# Parse the header to extract a user/password combo.
auth_header = webappRequest.request.headers.get('Authorization')
# if the auth header is missing popup a login dialog
if auth_header == None:
__basic_login(webappRequest)
else:
(username, password) = base64.b64decode(auth_header.split(' ')[1]).split(':')
if(__basic_lookup(username) == __basic_hash(password)):
return func(webappRequest, *args, **kwargs)
else:
__basic_login(webappRequest)
return callf
def __basic_login(webappRequest):
webappRequest.response.set_status(401, message="Authorization Required")
webappRequest.response.headers['WWW-Authenticate'] = 'Basic realm="Secure Area"'
def __basic_lookup(username):
accounts_file = os.getcwd() + os.sep + 'app' + os.sep + 'accounts.yaml'
stream = file(accounts_file, 'r')
for account in yaml.load(stream):
if account['username'] == username:
return account['password']
def __basic_hash(password):
return security.hash_password(password, method='sha1')
Примечание. Здесь используются префиксы с двойным подчеркиванием для функций, которые не должны быть видны за пределами модуля декораторов.
В этом случае неудачная попытка входа в систему просто вызовет другое диалоговое окно входа, я аутентифицируюсь, используя пароль, который хранится в отдельном файле accounts.yaml, а пароли хранятся в хешированной форме SHA1.
Код написан так, чтобы его можно было легко настроить:
- Измените __ basic_lookup () , если вам нужно, чтобы ваши пароли хранились где-то еще (например, в базе данных).
- Измените __ basic_hash () , если ваши пароли имеют открытый текст или кодируются другим способом.
- Измените __ basic_login () , если вы хотите другой ответ на неудачную попытку входа в систему. Например, искусственная задержка для предотвращения атак методом перебора или перенаправление.