强制内容类型或在Flask中公开request.data以获取已知内容类型

ytj*_*ohn 7 python base64 content-type flask

我正在使用Python/Flask重新创建服务,并且遇到了现有客户端进行身份验证的问题.出于兼容性原因,我必须匹配现有的客户端方案.

现有客户端使用用户名,密码和base64对其进行编码.这不是HTTP基本身份验证,尽管听起来很相似.下面是一些创建此登录请求的示例代码.

credentials = {
            'username': 'test@example.com',
            '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)
Run Code Online (Sandbox Code Playgroud)

在服务器端,我接受POST数据并对其进行解码,以便再次获取用户名和密码信息.

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')
Run Code Online (Sandbox Code Playgroud)

问题是内容类型.如果我在客户端(application/gooblygop)中指定了未知的Content-Type,Flask会将POST数据暴露给request.data,我可以解码base64字符串.如果我离开的Content-Type为默认值(应用程序/ x-WWW的形式,进行了urlencoded),原始数据不会暴露request.data,我不知道如何获取base64编码字符串,并利用它.

现有的客户端软件几乎默认为x-www-form-urlencoded,但我不能完全依赖于这种情况.

本质上,无论客户端程序指出什么Content-Type,我都需要一个可靠的服务器端方法来访问该编码字符串.

其他说明:我是Python的新手,来自PHP背景.所以我对建议很开放.此外,该项目主要供个人使用.

unm*_*ted 2

request.form在处理具有普通 mime 类型的 urlencoded 帖子时,您想要查看该对象。在这种情况下,您有一个不寻常的形式,但有一种方法可以做到这一点:

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

credentials = {
            'username': 'test@example.com',
            '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)
Run Code Online (Sandbox Code Playgroud)

您可能想要修改登录位来检查 mimetype,这里是对当前设置进行最小更改的版本:

@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)
Run Code Online (Sandbox Code Playgroud)

这是第一个代码示例的输出,有两个请求:

bvm$ python mkreq.py
application/gooblygop
username=test%40example.com&password=password
application/x-www-form-urlencoded
username=test%40example.com&password=password
Run Code Online (Sandbox Code Playgroud)