他のアプリケーションのユーザー名とパスワードを保存できるモデルを作成しようとしています。 Djangoでパスワードフィールドを設定して、adminでプレーンテキストにならないようにするにはどうすればよいですか?よろしくお願いします。
@mlissnerとして 推奨 the auth.User
モデルはよく見る場所です。 ソースコード を確認すると、password
フィールドがCharField
であることがわかります。
password = models.CharField(_('password'), max_length=128, help_text=_("Use
'[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change password form</a>."))
User
モデルにはset_password
方法。
def set_password(self, raw_password):
import random
algo = 'sha1'
salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
hsh = get_hexdigest(algo, salt, raw_password)
self.password = '%s$%s$%s' % (algo, salt, hsh)
この方法から、パスワードの作成と保存に関する手掛かりをいくつか入手できます。
通常のDjangoユーザーパスワードと同様の方法で保存された暗号化されたパスワードをハッシュ解除できるようになることはないと思います。セキュリティの一部は、非ハッシュ化可能。
残念ながら、この質問に対する簡単な答えはありません。これは、認証しようとしているアプリケーションに依存し、また、パスワードフィールドの安全性にも依存するためです。
Django=アプリケーションがパスワードを使用して、プレーンテキストのパスワードを送信する必要がある別のアプリケーションに対して認証を行う場合、オプションは次のとおりです。
Djangoの組み込みユーザーモデルを使用している場合は、マスターパスワードとしてDjangoユーザーパスワードを使用できます。これは、そのマスターパスワードをメモリに保持する必要があるため、一部の操作が困難になる可能性がありますサーバーの再起動や負荷分散された冗長サーバーの実行など。
幸いにも、多くの最新のアプリケーションは、パスワードベースではなくキーベースのアクセストークンシステムを使用して別の方法でこれをサポートしています。ユーザーは2つのアプリケーション間のリンクを設定するプロセスを案内され、舞台裏で、アプリケーションは永続的にまたは定義された有効期限で相互に認証するためのキーを生成します。
たとえば、Facebookはこのモデルをサポートしており、その仕組みに関する広範なドキュメントを持っています。
[OAuth 2.0](http://tools.ietf.org/html/draft-ietf-oauth-v2- 12)を使用してFacebookとリンクすることができたら、おそらくそれを使用して他のアプリケーションへのリンクを追加する方が簡単でしょう。同じプロトコル。
あなたの最善の策(私は知っています)は、Djangoコードのコードを詳しく調べて、それがどのように行われるかを確認することです。覚えているように、単純なテキスト値はどこにも保存されませんが、ハッシュとソルトは保存されます。
Djangoインストールに移動して、ハッシュやソルトなどの単語を探すと、すぐに見つけられるはずです。あいまいな答えで申し訳ありませんが、おそらく正しいパスに設定されるでしょう。 。
元に戻せるパスワードフィールドが必要な場合は、次のようなものを使用できます。
from Django.db import models
from Django.core.exceptions import ValidationError
from Django.conf import settings
from os import urandom
from base64 import b64encode, b64decode
from Crypto.Cipher import ARC4
from Django import forms
PREFIX = u'\u2620'
class EncryptedCharField(models.CharField):
__metaclass__ = models.SubfieldBase
SALT_SIZE = 8
def __init__(self, *args, **kwargs):
self.widget = forms.TextInput
super(EncryptedCharField, self).__init__(*args, **kwargs)
def get_internal_type(self):
return 'TextField'
def to_python(self, value):
if not value:
return None
if isinstance(value, basestring):
if value.startswith(PREFIX):
return self.decrypt(value)
else:
return value
else:
raise ValidationError(u'Failed to encrypt %s.' % value)
def get_db_prep_value(self, value, connection, prepared=False):
return self.encrypt(value)
def value_to_string(self, instance):
encriptado = getattr(instance, self.name)
return self.decrypt(encriptado) if encriptado else None
@staticmethod
def encrypt(plaintext):
plaintext = unicode(plaintext)
salt = urandom(EncryptedCharField.SALT_SIZE)
arc4 = ARC4.new(salt + settings.SECRET_KEY)
plaintext = u"%3d%s%s" % (len(plaintext), plaintext, b64encode(urandom(256-len(plaintext))))
return PREFIX + u"%s$%s" % (b64encode(salt), b64encode(arc4.encrypt(plaintext.encode('utf-8-sig'))))
@staticmethod
def decrypt(ciphertext):
salt, ciphertext = map(b64decode, ciphertext[1:].split('$'))
arc4 = ARC4.new(salt + settings.SECRET_KEY)
plaintext = arc4.decrypt(ciphertext).decode('utf-8-sig')
return plaintext[3:3+int(plaintext[:3].strip())]
暗号化の部分は https://djangosnippets.org/snippets/1330/ のスニペットに基づいており、フィールドモデルに変換し、utf-8サポートを追加し、回避策としてプレフィックスを追加しましたfor Djangoのto_python()のばかげた使用