2011-08-16 64 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