I created a user with a password password123 but in the database the password field look like this pbkdf2_sha256$260000$rJZWVrYXlokRG8fGMS1fek$S7Dm9soflUsy0Q74CJP8sB60tgfRWuRPdqj5XL0DBV0=
the problem: is when I create new user via rest framework i got the poassword feidl look like passsword123
so how should i created new user in order to keep the django password encoding functionality
also how to deactivate this password encoding functionality
Django uses encryption middlewares to encrypt passwords (since the database sees passwords as VarChar fields, so Django's model sees them as plain text unless it is told otherwise). If you want the Django User model to use encryption, you must call
user_obj.set_password(passwd_text)
With this line of code, you tell Django to run encryption algorithms. For example, in your case, you can first use the serializer's extra_kwargs to exclude passwords from database-readable data, then create the user.
class CreateUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'username', 'password']
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
password = validated_data.pop("password")
user = User(**validated_data)
user.set_password(password)
user.save()
return user
if you want to read more on Django users and passwords read these docs
user model doc and
encryption types and password management doc
you need to override create method in User Create Serializer:
class UserCreateSerializer(serializers.ModelSerializer):
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
return user
class Meta:
model = User
fields = "__all__" # or your specific fields
extra_kwargs = {
"password": {"write_only": True},
}
Now your user password will be saved as hashed password in database.
re. question 2.
Django does not store the password, only hashed value of the password, which it uses for comparison when the user logs in.
It is not possible to reverse engineer the password from this hash (well, mathematically it is possible, but you don't have the resources to run that process). Nor should it be.
If you wanted a password field that wasn't hashed, you would use just a string field. But... DON'T DO THIS! It is massively insecure.
There is no need for you to know the user's password.
As for question 1, I'm not sure why you're not seeing it hashed - you will need to post some code.
Related
I'm migrating something from an old PHP/apache server to Django. I'm a bit stumped with the 'ModelForm'.
As far as I understand, a "Model" is the abstraction for persistent elements in my website/server - specifically this is something stored physically, say in a database, and defines the fields (read columns) in the DB.
I started moving the authentication part of the site, and discovered models, and specifically the User model (I made an empty User inheriting AbstractUser just in case I will ever need to extend things). Now I want to create a simple two field form, to authenticate login.
The form:
Username (which is a field of User, by default)
Password (Which is not).
Even the 'Username' needs a redefinition in the model form. So my questions:
What is the advantage of the model form (over just a form)? - seems like you're redefining fields anyway, and obviously sometimes adding fields on top of the model.
Specifically for authentication, I probably need to store my salted hash associated with the user somehow, compare my password using that and retrieve the user object. This is something I find very hard to find in the Django docs - they just have too much written on authentication, and not one full code example. Do I put this in the "validate" method of form, retrieving there an object and storing it in a session or something?
If there is a deeper relation between a model form and the associated model, I would like to know as well.
Simple django forms and modelforms have quite differences.
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter']
The above example illustrates that you don't have to write any form field in here. The model form will itself create a form which is based on the attributes provided in the model ('Article' in this example).
If you create a simple django form then it would be something like:
class ArticleForm(forms.Form):
some_field = forms.CharField(some_attrs)
...
The django User model provides you everything you need for authentication. When you want to create users just import django.contrib.auth.models.User and use create method to create objects. Then when you want to authenticate a user use authenticate method.
from django.contrib.auth import authenticate, login
def user_login(request):
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
# after authentication login the user or set cookies or modify the session or some other action can be taken
return HttpResponse("Some response or use render for html page")
username and password will be coming from your post request.
If you want to extend default Django user model you can use django user model as onetoonefield in your extended model.
class AppUser(models.Model):
user = models.OneToOneField(User)
... # other custom fields
I am completely new to Django. In my models.py, I want a User model to represent users that sign into the application.
I see how I could have fields like fname, lname, email, and username, (simply add "first_name = models.CharField(max_length=50)", for example) but how would I have a password field so that users can be authenticated? Obviously it's a bad practice to store passwords in clear text.
There is built in django.contrib.auth user models which has following fields (username, firstname, lastname, password, email, groups, user_permissions, is_active, is_staff, is_superuser, last_login, last_joined)
you can use this built in user model by creating user object and setting password for it.
from django.contrib.auth.models import User
user = User.objects.create(username="username", password = "password", email="email")
user.save()
some fields in django user models are optional except username, password and email and by default it sets some fields like is_superuser='f' if you don't specify.
it will automatically store password in hash function and In future If you want to update any user's password you can get and update
user = User.objects.get(username="username")
user.set_password("password")
user.save()
You can get an current online user instance by request.user
Django's own AbstractBaseUser implementation:
#python_2_unicode_compatible
class AbstractBaseUser(models.Model):
password = models.CharField(_('password'), max_length=128)
last_login = models.DateTimeField(_('last login'), blank=True, null=True)
You store the password in a CharField, what you don't do is store it purely there, in fact calling the set_password for the user like below,
user.set_password("Password")
Would hash the "Password" and save it into the CharField.
Edit
If you don't base your class on AbstractBaseUser and want to implement a User class from scratch, you need to hash all passwords and then save them. Inorder to hash the passwords, you can use the make_password function.
from django.contrib.auth.hashers import make_password
hashed_password = make_password(raw_password)
The accepted answer is functional - as in it will not throw an error, but I don't think it is correct.
What I encountered was User.objects.create does not hash password, for that you should use User.objects.create_user
I have to store Customer information in a Customer table. We don't need to store their username and password. But to create customer groups and users, I'm using django's User and Group Models. Here is the customer Model which I use to store it's basic information.
class Customer(models.Model):
"""
The Customer
"""
UID = models.TextField(blank=True, null=True, db_index=True)
fk_user = models.ForeignKey(User, primary_key=False)
fk_details = models.ForeignKey(UserDetails, primary_key=False)
fk_contact_details = models.ForeignKey(ContactDetails, primary_key=False)
...
This is a class method which creates user object for which later I'm using it to store customer information :
from django.contrib.auth.models import User
def create_user(self, req_dict):
'''
Create a new User
'''
try:
user=User.objects.create_user(**req_dict)
user.save()
except:
return None
return user
But this code is throwing an IntegrityError which is because we are not passing username in the req_dict
req_dict = {'first_name': u'John', 'last_name': u'Smith', 'email': u'john.smith#xyz.com'}
What's the way to store username optional while creating a new user?
If you want to use django.contrib.auth you can't make the username field optional. You always have to put a value in the database.
In order to bypass that, I suggest you generate a value in create_user() for username. You could either use a random value, or create a username from email. Just make sure that it's unique.
You could make a pre_save signal to just provide default values
pre_save.connect(give_default_username, sender=User)
def give_default_username(sender, instance, *args, **kwargs):
instance.username = 'default'
Any time a user object's save method is invoked, it will go through this method first to append your required values before continuing with the save method.
I agree with #zanderle that it would be better to generate some username for your users. Maybe you can user their UID, or email, or something like this.
pre_save signal could solve your problem, but, as for me, it makes you system more implicit, because your models will be not consistent with your database.
Another way - to create some Default user for anonymous users. So, every db record will have user assignment and you will not force your customers to register.
I want to register a user in django-rest-auth, if all username, password and email fields are provided. (I want to implement token authentication too to obtain a JSON response from the server.)
The default email field in django.contrib.auth.User is optional. But I want to set the email filed as required to register in the database so that the user gets an HTTP error response when a POST request has been made without an email.
In the project I am registering the new user through the following code.
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', User.USERNAME_FIELD, "password", 'full_name',
'is_active', 'links', )
write_only_fields = ('password',)
read_only_fields = ('id',)
def create(self, validated_data):
print("Validated Data",validated_data)
if 'email' in validated_data:
user = get_user_model().objects.create(
username=validated_data['username']
)
user.set_email(validated_data['email'])
user.set_password(validated_data['password'])
user.save()
email = EmailMessage('Hello', 'World',
to=[validated_data['email']])
email.send()
user.is_active=False
return user
else:
return None
However, the above gives:
create() did not return an object instance
How do I set the email field as a required field?
I want to register an user in django-rest-auth, if all username, password and email fields are provided.
The correct way to require a field on a serializer in Django REST framework is to set required=True when initializing the field, or using the extra_kwargs parameter to set it on automatically generated fields.
In default email field in django.contrib.auth.User is optional. But I want to set the email filed as required to register in the database so that the user gets HTTP error response when POST request has been made without a email.
This means that the automatically generated field will not be required by default, but you can still override it with required=True.
However, the above gives:
create() did not return an object instance
This is because you are not returning a User instance from the create method, just like it says on the tin. Specifically, you are returning None if the email field is not included. None is not a User instance, and DRF is warning you that you're doing something wrong.
I have a setup with django-rest-framework, rest-auth, allauth and facebook Oauth2. My problem here is that when I created an user using the facebook endpoint, the social user was created, the django user was also created but both have no username. Should I configure this somewhere?
The username field is no longer present, because it was deprecated with Graph API v2.0 one year ago...
See
https://developers.facebook.com/docs/apps/changelog#v2_0_graph_api
/me/username is no longer available.
Check if you're using the newest versions of your libraries.
you can set custom username by overriding DefaultSocialAccountAdapter
i just removed # from email and replaced by _ to generate username
#in setting added this
SOCIALACCOUNT_ADAPTER = 'trip2.users.adapter.SocialAdapter'
# and then override the Adapter
class SocialAdapter(DefaultSocialAccountAdapter):
def populate_user(self,
request,
sociallogin,
data):
"""
Hook that can be used to further populate the user instance.
For convenience, we populate several common fields.
Note that the user instance being populated represents a
suggested User instance that represents the social user that is
in the process of being logged in.
The User instance need not be completely valid and conflict
free. For example, verifying whether or not the username
already exists, is not a responsibility.
"""
username = data.get('username')
first_name = data.get('first_name')
last_name = data.get('last_name')
email = data.get('email')
name = data.get('name')
user = sociallogin.user
emailtouname = email.split('#')[0] + "_" + email.split('#')[1].split('.')[0]
user_email(user, valid_email_or_none(email) or '')
name_parts = (name or '').partition(' ')
user_field(user, 'first_name', first_name or name_parts[0])
user_field(user, 'last_name', last_name or name_parts[2])
user_username(user, username or emailtouname)
return user
You can pass a 'username' key along with other data retrieved via Facebook API. Or you can dig into allauth/socialaccount/adapter.py populate_user() method and customize the 'username' field (I simply make it equal to user email)