改变Django的SECRET_KEY的影响

时间:2013-03-02 04:17:06

标签: django

我犯了一个错误,并将我的Django项目SECRET_KEY提交到公共存储库。

根据文档https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY

,该密钥应该保密

Django项目正在运行,并且已经与一些活跃用户运行了一段时间。如果我更改SECRET_KEY会有什么影响?任何现有用户,cookie,会话等都会受到影响吗?显然,新的SECRET_KEY将不再存储在公共场所。

5 个答案:

答案 0 :(得分:172)

编辑:此答案基于django 1.5

SECRET_KEY用于很多不同的地方,我会首先指出它受到什么影响,然后尝试查看该列表并准确解释其影响。

直接或间接使用SECRET_KEY的事项列表:

实际上,此处列出的很多项目使用SECRET_KEYdjango.utils.crypt.get_random_string(),它使用它来为随机引擎播种。这不会受到SECRET_KEY的价值变化的影响。

直接受价值变化影响的用户体验是:

  • 会话,数据解码将中断,这对任何会话后端(cookie,数据库,基于文件或缓存)都有效。
  • 密码重置令牌已经发送不起作用,用户将不得不问一个新的。
  • 评论表单(如果使用django.contrib.comments)将不会验证是否在值更改之前请求并在值更改后提交。我认为这是非常小的,但可能会让用户感到困惑。
  • 消息(来自django.contrib.messages)不会在与评论表单相同的时间条件下验证服务器端。

更新:现在正在研究django 1.9.5,快速浏览一下源代码,给出了几乎相同的答案。以后可能会进行彻底检查。

答案 1 :(得分:26)

自提出此问题以来,Django documentation已更改为包含答案。

  

密钥用于:

     
      
  • 如果您使用的是get_session_auth_hash()以外的任何其他会话后端,或者使用的是默认CookieStorage,则
  • 所有会话。
  •   
  • 如果您使用的是FallbackStoragePasswordResetView,则会收到所有消息。
  •   
  • 所有cd ~/junk # Go to some safe directory to create a new project. django-admin startproject django_scratch grep SECRET_KEY django_scratch/django_scratch/settings.py # copy to old project rm -R django_scratch 令牌。
  •   
  • 加密签名的任何用法,除非提供不同的密钥。
  •   
     

如果您旋转密钥,以上所有内容都将失效。密钥不用于用户密码,密钥轮换不会影响用户密码。

我不清楚我应该如何旋转密钥。我找到了关于Django generates a key for a new project的讨论以及讨论other options的要点的讨论。我最终决定让Django创建一个新项目,将新的密钥复制到我的旧项目中,然后擦除新项目

$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
s!)5@5s79sp=92a+!f4v!1g0d0+64ln3d$xm1f_7=749ht&-zi
$ ./manage.py shell -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
_)+%kymd=f^8o_fea1*yro7atz3w+5(t2/lm2cz70*e$2mn\g3
$

更新

看起来Django在版本1.10中添加了get_random_secret_key() function。您可以使用它来生成新的密钥。

<ScrollView
        android:id="@+id/SView"
        android:layout_below="@id/tvNama"
        android:layout_marginBottom="25dp"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@+id/sound">

  <FrameLayout
    android:id="@+id/scroll_view_frame"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

      <TextView android:id="@+id/tvketerangan"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:text="keterangan"
                android:textStyle="bold"
                android:textColor="#000000"
                android:textSize="16sp"/>
    <ImageView
      android:id="@+id/imageview"
      android:layout_width="300dp"
      android:layout_height="300dp"
      android:src="@drawable/sa"
      android:layout_below="@+id/tvketerangan"
      android:layout_centerHorizontal="true"/>
  </FrameLayout>

</ScrollView>

答案 2 :(得分:16)

根据这个页面https://docs.djangoproject.com/en/dev/topics/signing/,SECRET_KEY主要用于暂时性的东西 - 签署通过网络发送的数据,以便您可以检测到篡改。看起来可能会破坏的东西是:

  • 签名的Cookie,例如“记住我在这台计算机上的身份验证”类型值。在这种情况下,cookie将失效,签名将无法验证,用户将不得不重新进行身份验证。
  • 对于已请求密码重置或自定义文件下载链接的任何用户,这些链接将不再有效。用户只需重新请求这些链接。

有一些比我更近期和/或显着的Django经验的人可能会反感,但我怀疑除非你明确地使用签名API做一些事情,否则这只会给你的用户带来轻微的不便。

答案 3 :(得分:5)

SECRET_KEY字符串主要用于加密和/或散列cookie数据。由于默认会话cookie有其自身的缺点,因此很多框架(包括Django)都会出现这种情况。

想象一下,你在django中有表格用于编辑带有隐藏字段的文章。在此隐藏字段中存储您已编辑的文章的ID。如果您想确保没有人可以向您发送任何其他文章ID,您将添加一个带有散列ID的额外隐藏字段。因此,如果有人会更改ID,您就会知道它,因为哈希值不会相同。

当然这是一个简单的例子,但这就是使用SECRET_KEY的方式。

Django正在使用它作为例如{%csrf_token%}以及更多的东西。如果您根据自己的问题进行更改并且不使用它,那么它对您的应用程序确实不会产生任何影响。

唯一的问题是可能会话值将被删除。因此,例如用户将不得不再次登录管理员,因为django将无法使用不同的密钥解码会话。

答案 4 :(得分:0)

我犯了同样的错误。默认密码为50长,因此我使用powershell生成了50长的随机字符串,并用它替换了旧的SECRET_KEY。我已登录,并且在替换SECRET_KEY之后,我之前的会话已失效。

使用Powershell(source):

# Load the .net System.Web namespace which has the GeneratePassword function
[Reflection.Assembly]::LoadWithPartialName("System.Web")

#  GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
[System.Web.Security.Membership]::GeneratePassword(50,5)

使用Bash(source):

# tr includes ABCabc123 and the characters from OWASP's "Password special characters list"
cat /dev/urandom | tr -dc 'A-Za-z0-9!"#$%&\''()*+,-./:;<=>?@[\]^_`{|}~' | head -c 100 ; echo

在这一点上,我想为什么不尝试更大的键,所以我尝试了100和1000长的键。两者都起作用。如果我了解source code,则签名者函数返回的对象是base64中的hmac哈希。 RFC 2104的意思是HMAC密钥的所需长度。

  

使用键的时间更长的应用程序      比B字节先使用H哈希密钥,然后使用      所得的L字节字符串作为HMAC的实际密钥。

     

HMAC的密钥可以是任何长度(大于B字节的密钥是      首先使用H进行哈希处理)。但是,强烈建议少于L个字节      不鼓励这样做,因为这会降低安全性      功能。长度超过L个字节的密钥是可以接受的,但是额外的      长度不会显着增加功能强度。 (一种      如果密钥的随机性是      被认为是弱者。)

要翻译成普通话,密钥的大小必须与输出大小相同。密钥也需要以位为单位。 base64中的每个数字代表6位。因此,如果您拥有50个字符的密码,那么您将拥有一个50 x 6 = 300位的秘密密钥。如果使用SHA256,则需要一个256位密钥( sha256根据定义使用256位)。因此,除非您打算使用大于SHA256的哈希算法,否则50个长的密码应该可以工作。

但是由于密钥中的任何多余位都被散列,因此其大小不会显着降低性能。但这可以保证您有足够的位数用于较大的哈希函数。 SHA-512可以覆盖100个长的SECRET_KEY( 50 x 6 = 600位> 512位)。