Oto całkiem solidne wdrożenie wymyśliłem
Poprzez moich poszukiwań znalazłem ton niechlujstwa/niepełnych implementacji podstawowego dla GAE Internecie. W rezultacie skończyłem pisać własne. Jest to najlepsze/najprostsze podejście, jakie udało mi się wymyślić do tej pory.
Uważam za "dobrą praktykę" utrzymanie obsługi zleceń tak cienkich, jak to tylko możliwe. Aby wyciąć na płycie głównej i copypasta w samych opiekunach postanowiłem wprowadzić uwierzytelnienie jako dekorator. Aby go użyć, wystarczy dołączyć dekorator do metod get/post/put/handler'a.
Na przykład:
from decorators import basic_auth
class Handler(webapp2.RequestHandler):
@basic_auth
def get(self):
# load your page here
następnie dodać dekorator do 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')
Uwaga: Double podkreślenia ustalonej stosowane są tutaj na funkcjach, które nie powinny być widoczny poza modułem dekoratorów.
W tym przypadku nieudanej próby logowania po prostu wywoła kolejne okno logowania, mam uwierzytelniania przy użyciu hasła, które są przechowywane w oddzielnym pliku accounts.yaml i hasła są przechowywane w postaci hashed SHA1.
Kod jest napisany być łatwo dostosowane:
- Zmienić __basic_lookup() jeśli trzeba Hasła są przechowywane w innym miejscu (ex bazy danych).
- Zmienić __basic_hash() jeśli są hasła zwykłego tekstu lub zakodowane przy użyciu innej metody.
- Zmodyfikuj __basic_login(), jeśli chcesz uzyskać inną odpowiedź na nieudaną próbę logowania. Takich jak sztuczne opóźnienie, aby zapobiec atakom brutalnej siły lub przekierowaniu.
Czy to nie oznacza, że nikt nie znajduje strony dev? 01spor.com? Jeśli ktoś to znajdzie, może uzyskać do niego dostęp bez podstawowej warstwy "auth" przed nią. –