2011-08-16 107 views
7

我正在Python/Flask中重新創建服務,並且遇到了現有客戶端驗證方式的問題。出於兼容性原因,我必須匹配現有的客戶端方案。強制內容類型或在Flask中顯示已知內容類型的request.data

現有客戶端接受用戶名,密碼和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') 

的問題是內容類型。如果我在客戶端(應用程序/ gooblygop)中指定了未知的Content-Type,Flask將POST數據公開給request.data,並且我可以解碼base64字符串。如果我將Content-Type保留爲默認值(application/x-www-form-urlencoded),則原始數據不會暴露給request.data,我不知道如何檢索base64編碼的字符串並使用它。

現有的客戶端軟件幾乎都默認使用x-www-form-urlencoded,但我不能依賴於這種情況。

本質上,無論Content-Type客戶端程序狀態如何,我都需要一個可靠的服務器端方法來訪問編碼的字符串。

其他說明:我對Python很新,來自PHP背景。所以我非常樂於提供建議。此外,該項目主要供個人使用。

回答

2

您想在處理帶有正常mimetypes的urlencoded帖子時查看request.form對象。在這種情況下,你有一個不尋常的形式,但這裏是一個辦法做到這一點:你可能要修改登錄位檢查MIME類型

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

,這裏是用最少的更改當前設置一個版本:

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

這是第一個代碼示例的輸出,有兩個要求:

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

你有沒有想過使用JSON通過在POST數據? Flask已經構建了對傳遞json數據的支持。此外,如果設置在頭應用的內容類型/ JSON然後將燒瓶自動dejson爲您的POST數據,並把它放在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() 

這是燒瓶視圖

from flask import request 

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

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

我建議你測試使用curl以及如果你使用的是linux終端。這裏是一個例子

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

This is the username