Принудительно введите Content-Type или предоставьте request.data во Flask для известного типа содержимого - PullRequest
7 голосов
/ 17 августа 2011

Я воссоздаю службу в 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)

На стороне сервера я беру данные 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')

Проблема в типе контента.Если я указываю неизвестный Content-Type в клиенте (application / gooblygop), Flask предоставляет данные POST для request.data, и я могу декодировать строку base64.Если я оставлю Content-Type по умолчанию (application / x-www-form-urlencoded), необработанные данные не будут доступны для request.data, и я не знаю, как извлечь закодированную строку base64 и использовать ее.

В существующем клиентском программном обеспечении по умолчанию используется x-www-form-urlencoded, но я не могу полагаться на то, что это всегда так.

По сути, мне нужен надежный серверный метод для доступа к этой зашифрованной строке, независимо от того, какой тип содержимого указывает клиентская программа.

Другие примечания: я очень новичок в Pythonиз фона PHP.Так что я очень открыт для предложений.Также этот проект предназначен в первую очередь для личного пользования.

Ответы [ 2 ]

2 голосов
/ 17 августа 2011

Вы хотите посмотреть на объект request.form при работе с постами с кодировкой urlencode с обычными типами MIME. В этом случае у вас необычная форма, но вот способ сделать это:

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

Вы, вероятно, хотите изменить бит входа в систему, чтобы проверить 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)

Это вывод первого примера кода с двумя запросами:

bvm$ python mkreq.py
application/gooblygop
username=test%40example.com&password=password
application/x-www-form-urlencoded
username=test%40example.com&password=password
1 голос
/ 27 сентября 2011

Задумывались ли вы об использовании json для передачи ваших данных в POST?Flask имеет встроенную поддержку для передачи данных JSON.Кроме того, если вы зададите для Content-Type в заголовках значение application / json, то flask автоматически обработает данные 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()  

Это представление Flask

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
...