2015-04-28 3 views
2

У меня есть домен с не-ASCII символов, подобный http://blå.no домен зарегистрирован с Punycode эквивалент:Как обрабатывать проблемы utf-8 и punycode в промежуточном программном обеспечении Django csrf?

xn--bl-zia.no 

, который также установлен в Apache виртуальный хост:

<VirtualHost *:443> 
    ServerName xn--bl-zia.no 
    ... 

Проблема Я м наблюдение идет от запроса, содержащего:

'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko', 
'HTTP_HOST': 'xn--bl-zia.no', 
'SERVER_NAME': 'xn--bl-zia.no', 
'HTTP_REFERER': 'https://bl\xc3\xa5.no/login/ka/?next=/start-exam/participant-login/', 
'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest', 

ie. референт отправляется как utf-8, а не punycode. Исключение я получаю:

Traceback (most recent call last): 

    File "/srv/cleanup-project/venv/dev/lib/python2.7/site-packages/django/core/handlers/base.py", line 153, in get_response 
    response = callback(request, **param_dict) 

    File "/srv/cleanup-project/venv/dev/lib/python2.7/site-packages/django/utils/decorators.py", line 87, in _wrapped_view 
    result = middleware.process_view(request, view_func, args, kwargs) 

    File "/srv/cleanup-project/venv/dev/lib/python2.7/site-packages/django/middleware/csrf.py", line 157, in process_view 
    reason = REASON_BAD_REFERER % (referer, good_referer) 

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 10: ordinal not in range(128) 

Соответствующий код в csrf.py является:

  good_referer = 'https://%s/' % request.get_host() 
      if not same_origin(referer, good_referer): 
       reason = REASON_BAD_REFERER % (referer, good_referer) 

(get_host() использует SERVER_NAME из запроса)

Есть ли родной Джанго способ справиться с это, или мне нужно написать промежуточное программное обеспечение, которое преобразует utf-8 в punycode в доменной части заголовка ссылки?

ответ

0

Вот промежуточное программное решение ..

import urlparse 


class PunyCodeU8RefererFixerMiddleware(object): 
    def process_request(self, request): 
     servername = request.META['SERVER_NAME'] 
     if 'xn--' not in servername: 
      return None 

     referer = request.META.get("HTTP_REFERER") 
     if not referer: 
      return None 

     url = urlparse.urlparse(referer) 
     try: 
      netloc = url.netloc.decode('u8') 
     except UnicodeDecodeError: 
      return None 

     def isascii(txt): 
      return all(ord(ch) < 128 for ch in txt) 

     netloc = '.'.join([ 
      str(p) if isascii(p) else 'xn--' + p.encode('punycode') 
      for p in netloc.split('.') 
     ]) 
     url = url._replace(netloc=netloc) 
     request.META['HTTP_REFERER'] = urlparse.urlunparse(url) 
     return None 

пытается спасти как можно раньше, когда он обнаруживает, что не может ничего полезного сделать. Конечно, должно быть установлено до промежуточного программного обеспечения csrf.

 Смежные вопросы

  • Нет связанных вопросов^_^