LoginSignup
0
1

More than 5 years have passed since last update.

Andorid Chrome からのアクセスで、Django CSRF検証が失敗したりログインできなかったりする場合

Last updated at Posted at 2017-01-17

環境

Django 1.9
Android Chrome ( おそらくドルフィンとかでも )

現象

Django のログインフォームなどに Android の Chrome でアクセスした時、CSRF のエラー (403) が出てログインできない。

Django ログには CSRF cookie not set. のメッセージが残る。

概要

おそらく、リクエストクッキーにマルチバイトが含まれてサーバに送られています。

僕のケースでは、Google Analytics が入れたクッキー __utmz に日本語が入っていて、不具合が出てました。

それを Django が受取り、Python の http ライブラリのクッキーパーサ http.cookies の正規表現 http.cookies._CookiePattern でパースしますが、その正規表現パターンは flagsre.ASCII が指定されているので、マルチバイトが出てきた所でパースが終わってるようです。

対応

僕は WSGIRequest の COOKIES をパッチしました。マルチバイトをURLエンコードしてみました。

def patch_wsgi_request():
    """
    クッキーに日本語が含まれている場合、クッキーのパースが失敗するので
    パース前にURLエンコードする
    Android + Google Analytics でよく出る
    __utmz に日本語が入る
    """
    import re
    from urllib.parse import quote
    from django.core.handlers.wsgi import WSGIRequest
    from django import http
    from django.core.handlers.wsgi import get_str_from_wsgi
    from django.utils.functional import cached_property

    def _quote(s):
        return quote(s.group(0))

    def COOKIES(self):
        raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
        re_multibyte = re.compile(r'[^\x00-\x7F]+')
        raw_cookie_fixed = re_multibyte.sub(_quote, raw_cookie)
        return http.parse_cookie(raw_cookie_fixed)

    setattr(WSGIRequest, 'COOKIES', cached_property(COOKIES))

patch_wsgi_request()

このコードをどこか (urls.py の評価タイミングとか)で実行

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1