5

短いバージョン: django サイトでは、値を取得できますが、Twilio からの要求に応答することはできrequest.GETません。request.POSTcsrf と関係があると思われますが、問題をデバッグする方法がよくわかりません。詳細は以下。

長いバージョン: 私は、Twilio REST API を使用して SMS で医療調査を実行しているプロジェクトで友人を支援しています。私はドメインと、そのドメイン上に非常に必要最小限の django で構築されたサイトを持っていました。これは、django に慣れるために構築したものなので、それを使用しています。

調査に対する SMS 応答を収集しています。Twilio API の一部として、番号への応答をアカウントで指定された URL に送信するため、次のような応答をターゲットにしています。

...mydomain.com/some_page/another_page/

Twilio リクエストは次のようになります。

...mydomain.com/some_page/another_page/?AccountSid=###SOME_LONG_ACCOUNT_SIDE&From=%2BPHONE_NUMBER&Body=bla+BLA+bla+BLA&SmsSid=##MESSAGE_ID_KEY&SmsMessageSid=##MESSAGE_ID_KEY&FromCity=Santa+Cruz&FromState=California...

作業コード

私は、着信要求がAccountSid内部にあることをテストしています (データベースの値と比較して) views.py。アプリの場合、次のようなものがあります (これは機能します)。

from our_app import TwilioAccount
our_account = TwilioAccount.objects.get(id=1)

def twilio_response(request):
    assert request.GET.get('AccountSid', None) == our_account.account_sid
    ## log the incoming request to the database under survey responses...

動かないコード

Twilio アカウントにログインし、リクエスト メソッドをに切り替えてからPOSTすべてのデータ収集をに切り替えると、上記の assert ステートメントは失敗します。さらにデバッグすると、POST の下で QueryDict が空であることが明らかになったため、取得されたキー値はありません。request.POSTPOST: {}

これはおそらくPOST、django の下で が必要なためcsrf_tokenだと思いましたが、AccountSid のチェックはかなり良いと考えたのでcsrf_exempt、上記の関数をインポートしてラップしました。

@csrf_exempt
def twilio_response(request):
    assert request.POST.get('AccountSid', None) == our_account.account_sid
    ## log the incoming request to the database under survey responses...

AssertionError: ...

これはまったく同じリクエストでは機能しません: QueryDict は空です。


質問:

1) 作品を作るために他に何かする必要はあります@csrf_exemptか? 別の質問:これはひどくばかげた方法ですか? 実際にログインしているユーザーではなく、他社の API を使用している場合、人々は通常どのようにしてこの要件を満たすのでしょうか?

1a) csrf_exempt にする代わりに、GETaccount_sid に対してすべての着信要求を引き続きチェックしていることを知っているので、要求としてそのままにしておくことができます。私はそれを行うべきですか、それとも本当に単純な方法ですか?

2)これを行うための最良の方法を学びたいと思っています.djangoフォームを作成してから、リクエストをフォームにルーティングし、有効性をテストしてデータを消去する必要がありますか?もしそうなら、フォームのテンプレートがない場合に、ビュー/フォームがどのように見えるか (csrf_token で完成) について大まかな概要を誰か教えてもらえますか?

4

2 に答える 2

7

こちらのTwilio Developer EvangelistチームのMattです。

1) twilio_response 関数を @csrf_exempt でラップして、Django CSRF トークン チェックを削除するのが正しい方法です。Twilio は Django CSRF トークンを生成しません。代わりに、X-Twilio-Signature ヘッダーを使用した署名の検証など、POST が Twilio からのものであることを検証する他の方法があります。詳細については、Twilio セキュリティ ドキュメントを参照してください。

1a) テストとデバッグには GET リクエストを使用すると便利ですが、本番環境では POST を使用する必要があります。GET リクエストには HTTP 仕様によると本文がないため、結果はクエリ文字列で渡されます。最大長が 1600 文字のテキスト メッセージなど、パラメーターが大きすぎる場合、URL のクエリ文字列が URL の最大長を超え、文字列を処理するときに問題が発生する可能性があります。

2) Django フォームは、このユース ケースに適しています。特に、応答を保存するために使用される既存のモデルを活用する ModelForm です。たとえば、データを TwilioMessage モデルに保存する場合、ModelForm は次のようになります。

from django.forms import ModelForm
from .models import TwilioMessage


class MessageForm(ModelForm):
    pass

    class Meta:
        model = ReactionEvent
        # include all fields you're saving from the form here
        fields = ['body', 'to', 'from_', 'signature',] 
于 2014-01-13T21:21:46.203 に答える
0

私のオプションでは、settings.py で DEBUG(= True) を開きましたか? そして、DEBUG モードでは、An Exception(raise Exception('')) を発生させることができます。そして、url、GET、POST.etc.... のような環境 Varialbe を見ることができます。ページまたは return HttpResponse(request.POST) .dict()) を使用して post 変数を確認します。投稿するときは crsf_exempt を使用するのが正しい方法です

于 2013-08-12T23:19:45.877 に答える