質問

App Engine Dev Serverをセットアップして、プレビューのために他の人が利用できるようにしたいと思います。

その前に本当にやりたいことは、そのサイトから提供される任意のURLのHTTP認証を有効にすることです。そのステージを通過せずに誰もサービスにアクセスしたくありません。もちろん、私が開発しているアプリに独自のHTTP認証を作成することもできますが、アプリが展開されたときにその機能は必要ないので、それは完璧なソリューションではありません。

それを解決する良い方法はありますか?

役に立ちましたか?

解決

JavaまたはPythonを使用していますか?

Pythonを使用している場合は、既存のWSGIミドルウェアを使用してHTTP Basic Authを処理できます。ここにいくつかのオプションがあります:

他のヒント

アプリをAppengineサーバーに展開しますが、最終的には本番環境で使用するアプリIDとは異なるアプリIDを使用します。そうすれば、追加の認証メカニズムを開発する必要はなく、Dev APP Serverが複数のユーザー相当の負荷をどれだけうまく処理するかを心配する必要はありません。

dev_appserverに公開されないようにしないでください。それはそれのために設計されておらず、安全ではありません。 1つの問題に名前を付けるために、訪問者はYourHost/_ah/admin/およびDataStoreを混乱させることができます。LostTheoryによる認証の提案はそれを防ぎません。

絶対にこれを行う必要がある場合は、Apacheまたは別のWebサーバーを逆プロキシとして設定し、認証を実装し、 /_AH URLへのアクセスをブロックします。ただし、App Engineに展開するというPeterの提案は、はるかに優れたものです。

これが私が思いついたかなり堅実な実装です

私の検索を通して、私はオンラインのGAEのBasicAuthのずさんな/不完全な実装をたくさん見つけました。その結果、私は自分のものを書くことになりました。これは、私がこれまで思いつくことができた最良の/最も簡単なアプローチです。

リクエストハンドラーを可能な限り薄く保つのは「グッドプラクティス」だと思います。ハンドラー自体のボイラープレートとコピーパスタを削減するために、装飾器として認証を実装することにしました。それを使用するには、デコレーターをハンドラーのGet/Post/Put/Deleteメソッドに取り付けるだけです。

例えば:

from decorators import basic_auth

class Handler(webapp2.RequestHandler):
  @basic_auth
  def get(self):
    # load your page here

次に、デコレーターをデコレーターに追加します。

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')

注:ここでは、「デコレーター」モジュールの外側に見えるべきではない関数で、ダブルアンダースコアの接頭辞が使用されています。

この場合、失敗したログイン試行は単純に別のログインダイアログをポップアップするだけで、別のアカウントに保存されているパスワードを使用して認証します。YAMLファイル、パスワードはSHA1ハッシュドフォームに保存されます。

コードは簡単にカスタマイズされるように書かれています:

  • 変更 __basic_lookup() パスワードが必要な場合は、他の場所に保存されます(Exデータベース)。
  • 変更 __basic_hash() パスワードがプレーンテキストであるか、別の方法を使用してエンコードされている場合。
  • 変更 __basic_login() 失敗したログイン試行に対する別の応答が必要な場合。ブルートフォース攻撃を防ぐための人為的な遅延、またはリダイレクトなど。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top