我想设置 App Engine 开发服务器,以便其他人可以使用它进行预览。
在此之前我真正想做的是为从该站点提供的任何 URL 启用 HTTP 身份验证。我不希望任何人在未通过该阶段的情况下访问该服务。当然,我可以在我正在开发的应用程序中构建自己的 HTTP 身份验证,但这不是一个完美的解决方案,因为在部署应用程序时我不需要该功能。
有什么好的方法可以解决吗?
我想设置 App Engine 开发服务器,以便其他人可以使用它进行预览。
在此之前我真正想做的是为从该站点提供的任何 URL 启用 HTTP 身份验证。我不希望任何人在未通过该阶段的情况下访问该服务。当然,我可以在我正在开发的应用程序中构建自己的 HTTP 身份验证,但这不是一个完美的解决方案,因为在部署应用程序时我不需要该功能。
有什么好的方法可以解决吗?
您使用的是 Java 还是 Python?
如果您使用 Python,则可以使用现有的 WSGI 中间件来处理 HTTP 基本身份验证。以下是一些选项:
将应用程序部署到 appengine 服务器,但使用与您最终将在生产中使用的应用程序 ID 不同的应用程序 ID。这样您就不必开发任何额外的身份验证机制,并且您不必担心开发应用程序服务器将如何处理多个用户的负载价值。
不要让 dev_appserver 可公开访问。它不是为它设计的,也不安全。仅举一个问题,任何访问者都可以访问 yourhost/_ah/admin/ 并弄乱您的数据存储区,而 lost-theory 的 auth 建议不会阻止它。
如果您绝对必须这样做,请将 Apache 或其他网络服务器设置为反向代理,实现身份验证并阻止对 /_ah URL 的访问。不过,Peter 将其部署到 App Engine 的建议要好得多。
这是我想出的一个非常可靠的实现
通过我的搜索,我在网上发现了大量用于 GAE 的 BasicAuth 的草率/不完整的实现。结果,我最终写了自己的。这是迄今为止我能想到的最好/最简单的方法。
我认为让请求处理程序尽可能精简是一种“好习惯”。为了减少处理程序本身中的样板和copypasta,我决定将身份验证作为装饰器来实现。要使用它,只需将装饰器附加到处理程序的 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 散列形式存储。
代码编写为易于定制: