当我从
django-admin
创建用户时,用户密码已加密。
但是当我从 django shell 创建用户时,用户密码以纯文本形式保存。
示例:
{
"date_joined": "2013-08-28T04:22:56.322185",
"email": "",
"first_name": "",
"id": 5,
"is_active": true,
"is_staff": false,
"is_superuser": false,
"last_login": "2013-08-28T04:22:56.322134",
"last_name": "",
"password": "pbkdf2_sha256$10000$iGKbck9CED0b$6hWrKYiMPNGKhcfPVGal2YP4LkuP3Qwem+2ydswWACk=",
"resource_uri": "/api/v1/user/5/",
"username": "user4"
},
{
"date_joined": "2013-08-29T01:15:36.414887",
"email": "test@ophio",
"first_name": "",
"id": 6,
"is_active": true,
"is_staff": true,
"is_superuser": true,
"last_login": "2013-08-29T01:15:36.414807",
"last_name": "",
"password": "123test",
"resource_uri": "/api/v1/user/6/",
"username": "test3"
}
我正在尝试为一个简单的博客应用程序制作 REST 风格的 api : 当我尝试通过 post 请求 [通过传递 JSON] 插入用户时,密码将保存为纯文本。 如何覆盖此行为。
您不应该像其他人建议的那样通过正常的
User(...)
语法创建用户。您应该始终使用 User.objects.create_user()
,它可以正确设置密码。
user@host> manage.py shell
>>> from django.contrib.auth.models import User
>>> user=User.objects.create_user('foo', password='bar')
>>> user.is_superuser=True
>>> user.is_staff=True
>>> user.save()
为django创建超级用户最快的方法,在shell中输入:
python manage.py createsuperuser
要自动化脚本,您可以使用管道功能来执行命令列表,而不必每次都键入它。
### content of "create_user.py" file
from django.contrib.auth import get_user_model
# see ref. below
UserModel = get_user_model()
if not UserModel.objects.filter(username='foo').exists():
user=UserModel.objects.create_user('foo', password='bar')
user.is_superuser=True
user.is_staff=True
user.save()
记得先激活 VirtualEnv,然后运行以下命令(对于 Linux):
cat create_user.py | python manage.py shell
如果您使用窗口,则将 cat 命令替换为 type 命令
type create_user.py | python manage.py shell
或适用于 Linux 和 Windows
# if the script is not in the same path as manage.py, then you must
# specify the absolute path of the "create_user.py"
python manage.py shell < create_user.py
陷阱:不要在任何缩进块中包含空行,将其视为将代码粘贴到 REPL 中。如果你有任何空行,它将不起作用。
对于那些使用 django 1.9 或更高版本的人的回答,因为
from django.contrib.auth.models import User
已被弃用(可能更早),但肯定是在 1.9 之前。
而是这样做: 在bash中:
python manage.py shell
在python shell中创建一个带有密码的用户:
from django.apps import apps
User = apps.get_model('user', 'User')
me = User.objects.create(first_name='john', email='[email protected]') # other_info='other_info', etc.
me.set_password('WhateverIwant') # this will be saved hashed and encrypted
me.save()
如果来自 API,您可能应该应用这样的表单:
import json
User = get_model('User')
class UserEditForm(BaseModelForm):
"""This allows for validity checking..."""
class Meta:
model = User
fields = [
'first_name', 'password', 'last_name',
'dob', # etc...
]
# collect the data from the API:
post_data = request.POST.dict()
data = {
'first_name': post_data['firstName'],
'last_name': post_data['firstName'],
'password': post_data['password'], etc.
}
dudette = User() # (this is for create if its edit you can get the User by pk with User.objects.get(pk=kwargs.pk))
form = UserEditForm(data, request.FILES, instance=dudette)
if form.is_valid():
dudette = form.save()
else:
dudette = {'success': False, 'message': unicode(form.errors)}
return json.dumps(dudette.json()) # assumes you have a json serializer on the model called def json(self):
您可以使用
user.set_password
在 django shell 中设置密码。我什至不确定通过 user.password
直接设置密码是否有效,因为 Django 需要密码的哈希值。
password
字段不存储密码;它将它们存储为 <algorithm>$<iterations>$<salt>$<hash>
,因此当它检查密码时,它会计算哈希值并进行比较。我怀疑用户实际上拥有一个密码,其计算出的密码哈希值采用 <algorithm>$<iterations>$<salt>$<hash>
形式。
如果您获得
json
以及创建用户所需的所有信息,您可以这样做
User.objects.create_user(**data)
假设您传递的 json 称为 data。
注意:如果
data
中有多余或缺失的项目,这将引发错误。
如果你真的想覆盖这个行为,你可以这样做
def override_setattr(self,name,value):
if name == 'password':
self.set_password(value)
else:
super().__setattr__(self,name,value) #or however super should be used for your version
User.__setattr__ = override_setattr
我还没有测试过这个解决方案,但它应该有效。使用风险自负。
要创建用户,请执行:
$ python manage.py shell
>>>> from django.contrib.auth.models import User
>>>> user = User.objects.create_user('USERNAME', 'MAIL_NO_REQUIRED', 'PASSWORD')
所有正确的想法。只是分享我的方法。我将其添加到我的用户管理器中。
user = get_user_model()
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def _create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError(_("The Email must be set"))
try:
with transaction.atomic():
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
except:
raise
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_active", True)
if extra_fields.get("is_staff") is not True:
raise ValueError(_("Superuser must have is_staff=True."))
if extra_fields.get("is_superuser") is not True:
raise ValueError(_("Superuser must have is_superuser=True."))
return self._create_user(email, password, **extra_fields)
然后我这样使用它:
user.objects.create_superuser(email="[email protected]", password="SecretPwd")
有几种方法可以从 django-shell 为 django 用户对象设置密码。
user = User(username="django", password = "secret")
user.save()
这将存储加密的密码。
user = User(username="django")
user.set_password("secret")
user.save()
这将存储加密的密码。
但是,
user = User(username="django")
user.password="secret"
user.save()
这将存储纯文本密码。由于您直接修改属性,因此没有应用哈希/加密。