5

我有一个 django 表单来获取用户名、密码。当用户发布数据时,我看到帖子字典包含以下内容(回溯),回溯(最近一次调用):

File "/usr/lib/python2.4/site-packages/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)

File "/usr/lib/python2.4/site-packages/django/views/decorators/csrf.py", line 39, in wrapped_view
resp = view_func(*args, **kwargs)

File "/usr/lib/python2.4/site-packages/django/views/decorators/csrf.py", line 52, in wrapped_view
return view_func(*args, **kwargs)

File "/public/gdp/trunk/src/ukl/lis/process/utils/error_handler.py", line 17, in __call__
return self.function(*args, **kwargs)

File "/usr/lib/python2.4/site-packages/django/views/decorators/cache.py", line 66, in _cache_controlled
response = viewfunc(request, *args, **kw)

File "/public/gdp/trunk/src/ukl/lis/process/authentication/views.py", line 530, in process_login
form = loginForm(request.POST)

File "/usr/lib/python2.4/site-packages/django/core/handlers/modpython.py", line 101, in _get_post
self._load_post_and_files()

File "/usr/lib/python2.4/site-packages/django/http/__init__.py", line 270, in _load_post_and_files
if self.META.get('CONTENT_TYPE', '').startswith('multipart'):

AttributeError: 'NoneType' object has no attribute 'startswith'

<ModPythonRequest
path:/login.html,
GET:<QueryDict: {}>,
POST:<could not parse>,
COOKIES:{'__utma': '115966011.1553834174.1346687405.1346687405.1346687045.1',
'__utmb': '115962011.4.10.1346687045',},
META:{'AUTH_TYPE': None,
'CONTENT_LENGTH': '85',
'CONTENT_TYPE': None,
'GATEWAY_INTERFACE': 'CGI/1.1',
'HTTP_ACCEPT': 'text/html, application/xhtml+xml, */*',
'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
'HTTP_ACCEPT_LANGUAGE': 'en-GB',
'HTTP_CACHE_CONTROL': 'no-cache',
'HTTP_CONNECTION': 'Keep-Alive',
'HTTP_CONTENT_LENGTH': '85',
'HTTP_COOKIE': 'flavor=desktop; sessionid=4a2f2ab6f61315493f3038338524cfc7;    tmsid=e7c921af-9cae-4f58-8825-13f9bc2ba95f; uniqid=6f69c607-6aca-4e92-a112-b83691805155; __utma=115962011.1553833174.1346687005.1346687005.1346687005.1; __utmb=115962011.4.10.1346687005; __utmz=115962011.1346687005.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmc=115962011',
'HTTP_HOST': 'example.com',
'HTTP_REFERER': 'http://example.com/',
'HTTP_USER_AGENT': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64;  Trident/5.0)',
'PATH_INFO': u'/login.html',
'PATH_TRANSLATED': None,
'QUERY_STRING': None,
'REMOTE_ADDR': 'xx.xx.xx.xx',
'REMOTE_HOST': None,
'REMOTE_IDENT': None,
'REMOTE_USER': None,
'REQUEST_METHOD': 'POST',
'SCRIPT_NAME': '',
'SERVER_NAME': 'example.com',
'SERVER_PORT': 443,
'SERVER_PROTOCOL': 'HTTP/1.1',
'SERVER_SOFTWARE': 'mod_python'}>

为什么 post dict 有“<could not parse>”,为什么 CONTENT_TYPE 没有?这可以防止我越过登录页面。

这是我的表格

   <form method="POST">{% csrf_token %}
       <tr>
     <td><label>Email Id</label></td>
     <td>{{form.username}}</td>
     <td><label>Password</label></td>
     <td>{{form.password}}</td>
   </tr>
    <input type="submit" name="btn_login" id="btn_login" class="btn_login" value="Login" /></td>

  </form>

表格.py:

class loginForm(ModelForm):
    username = forms.CharField(max_length=50)
    password = forms.CharField(max_length=50, widget=forms.PasswordInput(attrs=  {"autocomplete":"off"}))

    class Meta:
        model = User

看法:

def login(request):
 if request.method == "POST":
   log.inof(request)
 else:
  request.session.set_test_cookie()
  form = loginForm()
  return render_to_response('login.html', {'form':form},context_instance=RequestContext(request))

注意:我还发现所有请求都来自移动设备,尤其是黑莓。似乎还有一个用户有同样的问题

参考:https ://stackoverflow.com/questions/12471661/mod-python-could-not-parse-the-django-post-request-for-blackberry-and-some-andro

4

4 回答 4

5

由于您的开发堆栈上不会发生该错误,因此有时在生产中我怀疑它是否在您的 Django 代码中。

你是如何联系机器的?请求将发送到本地主机。您是在生产机器上运行浏览器,还是在它前面有一些代理或负载均衡器?

在我看来,在您的请求到达 mod_python 之前,有些东西正在破坏您的请求,无论是代理还是配置错误的 ssl。

症状是您收到中断的请求。问题可能出在您的 python 应用程序的任何地方,从您端的所有 OSI 层到客户端的所有 OSI 层。尝试全面了解介于两者之间的所有事物并系统地排除它们。

您的 TCP/IP 堆栈似乎工作正常,否则您会看到其他请求和服务也受到影响。所以我们可以排除会话层以下的一切。剩下的是表示层 (SSL) 和应用层 (HTTP)。

  1. SSL

    SERVER_PORT 是 443,SSL 在这里起作用。请求标头(HTTP_REFERER 等)包含有效字符串,因此 SSL 似乎工作正常。但我以前见过一些奇怪的混乱的 TLS 会话。

  2. HTTP

    这一层的玩家:

    • 你的 Apache httpd
    • 您的任何反向代理
    • 您和客户之间的任何转发代理。REMOTE_ADDR 是否都在同一个子网中,是否有一些移动运营商的代理损坏?
    • 客户端用户代理。所有的黑莓都坏了吗?尝试使用您认为最失败的浏览器。

您的负载均衡器在哪一层运行?

似乎主要问题是 POST 请求中缺少 Content-Type 标头,因此在 Python 表示的 POST 内容上的值无法使用 pprint 打印出来,更不用说您的应用程序使用了。

忽略在 Blackberry developer ref 中找到的内容:您是否尝试过按照Simon 的建议明确设置 enctype ?尝试改变application/x-www-form-urlencodedmultipart/form-data

最重要的是尝试自己复制它。尝试制作一个记录此类请求的tcpdump您可以使用wireshark分析记录的转储。

于 2012-09-17T16:07:37.117 回答
4

您可以尝试使用 mod_wsgi 而不是 mod_python 进行部署吗?我将从那里开始,它可能不是 django 错误,否则每个人都会收到错误,而不仅仅是破解莓用户。Mod_python 已经很老了,我遇到了更多关于 mod_wsgi 的问题。

于 2012-09-18T18:26:44.993 回答
3

django/core/handlers/wsgi.py 似乎把消息放在那里;你可以破解代码并将str(异常)也放在那里。

但是,我的猜测是您没有正确指定字符集;django 假设为 UTF-8,并且表单以 python 无法解码的一些完全随机的字符集提交,也许?此外,您可能想尝试删除 CSRF 中间件一段时间,并尝试在没有它的情况下它是否可以工作。

于 2012-09-13T11:56:32.397 回答
3

也许黑莓客户端 gzip 他们的 POST 正文以节省带宽?Django 不会自动解码 gzip 压缩的消息(至少在 Django 1.3.1 中)。在您看来,尝试解码原始 POST 数据

import zlib
post_data = zlib.decompress(request.raw_post_data, 16+zlib.MAX_WBITS)

通常,HTTP_CONTENT_ENCODING应该设置 HTTP 标头,但负载均衡器可能会不小心将其剥离?

于 2012-09-18T08:02:20.430 回答