---
title: "Django 1.9.3 版本发行说明"
version: 5.0
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/5.0/releases/1.9.3/
canonical: https://djangodocs.dev/zh-hans/5.0/releases/1.9.3/
---
# Django 1.9.3 版本发行说明

*2016 年 3 月 1 日*

Django 1.9.3 修复了 1.9.2 版本中的两个安全问题和一些错误。

## CVE-2016-2512 ：通过包含基本身份验证的用户提供的重定向 URL，可能存在恶意重定向和 XSS 攻击。

Django 在某些情况下（例如 `django.contrib.auth.views.login()` 和 i18n \</topics/i18n/index\>\`）依赖用户输入来将用户重定向到“成功” URL。用于这些重定向的安全检查（即 `django.utils.http.is_safe_url()`）在考虑到某些具有基本身份验证凭据的 URL 时将其视为“安全”，但它们实际上不应该被视为安全。

例如，如果请求的主机是 `http://mysite.example.com`，那么类似 `http://mysite.example.com\@attacker.com` 的 URL 将被视为安全，但重定向到此 URL 会将用户发送到 `attacker.com`。这是一个潜在的安全风险。

此外，如果开发人员依赖于 `is_safe_url()` 来提供安全的重定向目标，并将这样的 URL 放入链接中，他们可能会受到 XSS 攻击的影响。

## CVE-2016-2513 ：通过密码哈希器工作因子升级的时间差异进行用户枚举。

自从 Django 1.6 版本以来，`PBKDF2PasswordHasher` 及其子类的默认迭代次数已经增加。这提高了密码的安全性，因为硬件的速度增加，但它也在登录请求中创建了一个时序差异，对于使用旧迭代次数编码的密码的用户和不存在用户的登录请求（从 Django 1.6 开始运行默认哈希的默认迭代次数）之间存在时序差异。这可能会对安全性产生一定的影响。

这只影响那些自增加迭代次数以来尚未登录的用户。当用户在迭代次数增加后首次登录时，他们的密码将使用新的迭代次数进行更新，因此不再存在时间差异。

新的 `BasePasswordHasher.harden_runtime()` 方法允许哈希算法在现有编码密码中提供的工作因素（例如迭代次数）和哈希算法的默认工作因素之间弥合运行时差距。这个方法已经在 `PBKDF2PasswordHasher` 和 `BCryptPasswordHasher` 中实现。后者的哈希算法自从 Django 1.4 以来并没有改变，但某些项目可能会对其进行子类化，并根据需要增加工作因素。

对于任何未实现 `harden_runtime()` 方法的 [第三方密码哈希算法](/zh-hans/5.0/topics/auth/passwords/#write-your-own-password-hasher)，将发出警告。

如果在数据库中有不同的密码哈希值（例如，自从 Django 1.4 开始默认哈希算法切换到 PBKDF2 后从未登录过的用户的 SHA1 哈希值），则这些用户的登录请求中的时序差异可能会更大，而此修复不会解决这种差异（或在更改哈希算法时的任何差异）。您可以尝试 [升级这些哈希值](/zh-hans/5.0/topics/auth/passwords/#wrapping-password-hashers)，以防止这种情况下的时序攻击。

## 漏洞修复

- 如果未定义 `ROOT_URLCONF` 设置，则跳过 URL 检查（在 1.9 中新增）（[#26155](https://code.djangoproject.com/ticket/26155)）。
- 修复了在 PostgreSQL 上的崩溃问题，该问题阻止了使用 `TIME_ZONE=None` 和 `USE_TZ=False` ([#26177](https://code.djangoproject.com/ticket/26177))。
- 添加了系统检查来检查隐藏关系的查询名称冲突 ([#26162](https://code.djangoproject.com/ticket/26162))。
- 修复了在 `ForeignObject.get_extra_descriptor_filter()` 返回 `Q` 对象的情况下导致的回归问题（[#26153](https://code.djangoproject.com/ticket/26153)）。
- 修复了在为设置了 `to_field` 的 `ForeignKey` 使用 `__in=qs` 查找时导致的回归问题（[#26196](https://code.djangoproject.com/ticket/26196)）。
- 使 `forms.FileField` 和 `utils.translation.lazy_number()` 可以被序列化 ([#26212](https://code.djangoproject.com/ticket/26212))。
- 修复了在使用 `None` 值时的 [`RangeField`](/zh-hans/5.0/ref/contrib/postgres/fields/#django.contrib.postgres.fields.RangeField) 和 [`ArrayField`](/zh-hans/5.0/ref/contrib/postgres/fields/#django.contrib.postgres.fields.ArrayField) 序列化问题 ([#26215](https://code.djangoproject.com/ticket/26215))。
- 修复了在 `RawQuery` 中使用 `Decimal` 进行过滤时导致崩溃的问题（[#26219](https://code.djangoproject.com/ticket/26219)）。
- 允许了 `URLValidator` 检查的 URL 顶级域名中的连字符，以修复 Django 1.8 中的一个回归问题 ([#26204](https://code.djangoproject.com/ticket/26204))。
- 修复了在 Django 1.9 中回归的 `SimpleTemplateResponse` 中一些导致崩溃的废弃 shims（[#26253](https://code.djangoproject.com/ticket/26253)）。
- 修复了 `BoundField` 以重新允许对子部件进行切片 ([#26267](https://code.djangoproject.com/ticket/26267))。
- 更改了管理界面登录模板中的“权限被拒绝”的消息，使用 `get_username` 而不是 `username`，以支持自定义用户模型（[#26231](https://code.djangoproject.com/ticket/26231)）。
- 修复了在将不存在的模板名称传递给缓存模板加载器的 `load_template()` 方法时导致崩溃的问题（[#26280](https://code.djangoproject.com/ticket/26280)）。
- 防止了 `ContentTypeManager` 实例共享其缓存 ([#26286](https://code.djangoproject.com/ticket/26286))。
- 回滚了 Django 1.9.2 中的一个更改（[#25858](https://code.djangoproject.com/ticket/25858)），该更改阻止了在抽象模型上定义的相对延迟关系根据其具体模型的 `app_label` 解析的更改（[#26186](https://code.djangoproject.com/ticket/26186)）。
