app引擎开发服务器中的HTTP身份验证

时间:2009-08-25 00:45:28

标签: google-app-engine http-authentication

我想设置应用引擎开发服务器,以便其他人可以进行预览。

在此之前我真正想做的是为该网站提供的任何网址启用http身份验证。我不希望任何人在没有通过该阶段的情况下访问该服务。我当然可以在我正在开发的应用程序中构建我自己的http身份验证,但这不是一个完美的解决方案,因为我在部署应用程序时不需要该功能。

有什么好方法可以解决吗?

4 个答案:

答案 0 :(得分:2)

您使用的是Java还是Python?

如果您使用的是Python,则可以使用现有的WSGI中间件来处理HTTP基本身份验证。以下是一些选项:

答案 1 :(得分:2)

将应用程序部署到appengine服务器,但使用的应用程序ID与最终在生产中使用的应用程序ID不同。这样您就不必开发任何额外的身份验证机制,并且您不必担心开发应用服务器处理多个用户负载的程度。

答案 2 :(得分:2)

不要公开访问dev_appserver。它不是为它设计的,而且不安全。仅列举一个问题,任何访问者都可以访问您的主机/ _ah / admin /并弄乱您的数据存储区,而丢失理论的auth建议也不会阻止它。

如果您绝对必须这样做,请将Apache或其他网络服务器设置为反向代理,实施身份验证并阻止对/ _ah网址的访问。然而,Peter建议将它部署到App Engine是一个更好的建议。

答案 3 :(得分:2)

这是我提出的非常可靠的实现

通过我的搜索,我在网上找到了大量基于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散列形式存储。

代码编写为易于自定义:

  • 修改 __ basic_lookup()如果您需要将密码存储在其他地方(例如数据库)。
  • 修改 __ basic_hash(),如果您的密码是纯文本或使用其他方法编码。
  • 如果您希望对失败的登录尝试做出不同的响应,请修改 __ basic_login()。例如人为延迟以防止暴力攻击或重定向。