2011-08-16 2 views
7

サービスをPython/Flaskで再作成していて、既存のクライアントの認証方法に問題があります。互換性の理由から、既存のクライアント方式と一致させる必要があります。コンテンツを強制するFlaskで既知のコンテンツタイプを入力または公開します

既存のクライアントはusername、passwordを使用し、base64はそれをエンコードします。 HTTPの基本認証ではありませんが、これは似たようなものです。以下は、このログイン要求を作成するサンプルコードです。

credentials = { 
      'username': '[email protected]', 
      'password': 'password' 
} 
data = b64encode(urlencode(credentials)) 
request = urllib2.Request(loginURL) 
request.add_data(data) 
# request.add_header('Content-Type', 'application/gooblygop') 
# 'application/x-www-form-urlencoded' seems to be a default Content-Type 
login = urllib2.urlopen(request) 

サーバー側では、POSTデータを取得し、base64でデコードしてユーザー名とパスワード情報を再度取得します。

flask server: 
@app.route('/login', methods=['POST']) 
def login(): 
    error = None 
    if request.method == 'POST': 
     # post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20= 
     data = b64decode(request.data) 
     # decoded data: password=default&email=test%40example.com 
     return('ok') 

問題はコンテンツタイプです。クライアント(application/gooblygop)に未知のContent-Typeを指定すると、FlaskはPOSTデータをrequest.dataに公開し、base64文字列をデコードできます。 Content-Typeをデフォルト(application/x-www-form-urlencoded)のままにしておくと、生データはrequest.dataに公開されず、base64でエンコードされた文字列を取得して使用する方法がわかりません。

既存のクライアントソフトウェアはすべてデフォルトでx-www-form-urlencodedになっていますが、これは常に当てはまるとは限りません。

本質的に、クライアントプログラムがどのようなContent-Typeに関係なく、コード化された文字列にアクセスするための信頼できるサーバー側のメソッドが必要です。

その他の注意事項:私はPHPのバックグラウンドから来た、Pythonの新機能です。だから私は非常に提案に開放されています。また、このプロジェクトは主に個人用です。

答えて

2

通常のMIMEタイプのURLエンコードされた投稿を処理する場合は、request.formオブジェクトを見たいと思っています。この場合、あなたは珍しい形を持っていますが、ここでそれを行う方法です:

# mkreq.py 
from urllib import urlencode 
import urllib2 
from base64 import b64encode 

credentials = { 
      'username': '[email protected]', 
      'password': 'password' 
} 
data = b64encode(urlencode(credentials)) 
request = urllib2.Request("http://localhost:5000/login") 
request.add_data(data) 
request.add_header('Content-Type', 'application/gooblygop') 
# 'application/x-www-form-urlencoded' seems to be a default Content-Type 
login1 = urllib2.urlopen(request).read() 
print(login1) 
request2 = urllib2.Request("http://localhost:5000/login") 
request2.add_data(data) 
login2 = urllib2.urlopen(request2).read() 
print(login2) 

おそらく、MIMEタイプをチェックするためにログインビットを変更したい、ここにあなたの現在の設定に最小限の変更でバージョンは次のとおりです。

@app.route('/login', methods=['POST']) 
def login(): 
    error = None 
    if request.method == 'POST': 
     # post data: cGFzc3dvcmQ9ZGVmYXVsdCZlbWFpbD10ZXN0JTQwZXhhbXBsZS5jb20= 
     data = b64decode(request.data) 
     # decoded data: password=default&email=test%40example.com 
     if not data: 
      data = b64decode(request.form.keys()[0]) 
     special_mimetype = request.mimetype 
     return(special_mimetype + '\n' + data) 

これは、2つのリクエストで、最初のコードサンプルの出力です:

bvm$ python mkreq.py 
application/gooblygop 
username=test%40example.com&password=password 
application/x-www-form-urlencoded 
username=test%40example.com&password=password 
1

あなたはPOSTでデータを渡すためにJSONを使用して考えたことはありますか? Flaskにはjsonデータを渡すためのサポートが組み込まれています。アプリケーション/ JSONにヘッダ内のContent-Typeを設定した場合また、その後、フラスコは、自動的にあなたのためのPOSTデータdejsonとrequest.jsonに

をそれを置くここで要求するアプリケーション

import urllib2 
import json 

if __name__ == "__main__": 
    headers = {'Content-Type':'application/json'} 
    post_data = {"user":"test_user"} 
    print "Posting request" 
    req = urllib2.Request("http://localhost:5000/login", json.dumps(post_data), headers) 
    resp = urllib2.urlopen(req) 
    print "Response was %s" % resp.read() 

がありますこれはFlaskビューです

from flask import request 

@app.route('/login', methods=['POST']) 
def login(): 

    user = request.json['user'] 
    return user 

linux端末を使用している場合は、カールを使用してテストすることをお勧めします。ここに例があります

curl -X POST -H "Content-Type:application/json" -s -d '{"user":"This is the username"}' 'localhost:5000/login' 

This is the username 
関連する問題