I am working a project which is like CMS (Content Management System) for a website. I am developing this system with django python. But I am new to django python.
I have my own User model (not django user model) that contains some fields like username, email, password etc. and I create new user from my own admin panel.
How can I compare encrypted password with user's password that post on login page.
For example first time I create user, the password for 123 saved on db like pbkdf2_sha24123$000asd$... After that I am trying to login with password 123 but I get error that the passwords are not equals.
from django.contrib.auth.hashers import make_password
from account.models import myUsers
password = make_password(request.POST.get('password'))
email = request.POST.get('email')
if myUsers.password == password and myUsers.email == email:
#make login and redirect to panel
else:
#show error message
my own model like;
class myUsers(models.Model):
username = models.CharField(max_length=25, verbose_name='username', unique=True)
email = models.CharField(max_length=225, verbose_name='email', unique=True)
password = models.CharField(max_length=225, verbose_name='password')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='created date')
secret_question = models.CharField(max_length=225, verbose_name='secret question')
secret_answer = models.CharField(max_length=225, verbose_name='secret answer')
last_login = models.DateTimeField(verbose_name='last login')
secret_guid_key = models.CharField(max_length=15, verbose_name='recover key', unique=True, editable=False, default=uuid.uuid4().hex[:15])
user_role = models.CharField(max_length=6, verbose_name='member role')
A User Object has a method called check_password() that hashes and checks your plain text password against the hashed password stored in the DB.
https://docs.djangoproject.com/en/2.2/ref/contrib/auth/#django.contrib.auth.models.User.check_password
Example Usage:
from account.models import myUsers
password = request.POST.get('password')
email = request.POST.get('email')
user = myUsers.objects.get(email=email)
if user.check_password(password):
# Success Code
else:
# Error Code
i think you should try django authenticate function.
user = authenticate(username=username, password=password)
You shuoldn't compare passwords:
if myUsers.password == password ..:
but rather the hash of the password:
if myUsers.password == myPasswordHashFunction(password) ..:
how to write myPasswordHashFunction is something you should know in detail, or you're better off using django's authenticate function.
If you're not a security expert, then please (please!) don't invent your own way to authenticate and authorize users.
try this code:
from django.contrib.auth.models import auth
from django.contrib import messages
def signin(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user:
auth.login(request, user)
return redirect('/')
else:
messages.info(request, 'Invalid credentials!!')
return redirect('signin')
else:
return render(request, 'signin.html')
In default, the Django authentication system provided in django.contrib.auth requires the end user to authenticate themselves using a username and password.
If you're using email and password for user authentication, you need a custom authentication backend. This link will help you.
Link : https://stackoverflow.com/a/37332393/9563316
If you use username and password for user authentication. You should try something like this.
from django.contrib.auth import authenticate, login
from django.contrib import messages
def userLogin(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('somewhere-you-want')
else:
messages.error(request, 'Invalid user login credentials!')
return redirect('userLogin')
else:
return render(request, 'login.html')
See docs here : https://docs.djangoproject.com/en/3.0/topics/auth/default/
Related
I am trying to set up a login page and I am trying to use the #login_required decoration. However, whenever I try and log in with valid credentials I am re-directed to the 'login' page (set to re-direct unauthenticated users). I am not sure if the problem is in the #login_required decoration or perhaps the login() function is not authenticating the user.
Here is my code for the register form:
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
confirm_password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email', 'password']
code for login function in views.py:
def login_user(request):
if request.method =="GET":
return render(request, "main/login.html", {})
else:
username = escape(request.POST['userfield'])
password = escape(request.POST['passfield'])
try:
user = User.objects.get(username=username)
except:
user = None
if user is None:
try:
user = User.objects.get(email=username)
except:
user = None
if user is None:
messages.info(request, "*Sorry, that username or email does not exist")
return redirect('login')
pword = user.password
if check_password(password, pword):
login(request, user)
return redirect('homepage')
else:
messages.info(request, '*Sorry, that was an incorrect password')
return redirect('login')
my model for User in models.py:
class User(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
username = models.CharField(max_length=100)
email = models.EmailField(unique=True)
password = models.CharField(max_length=100)
admin = models.BooleanField(default=False)
last_login = models.DateTimeField(null=True, blank=True)
and my function to reach the 'homepage' after login:
#login_required(redirect_field_name='login')
def homepage(request):
return render(request, "main/homepage.html", {})
When you make custom user model, so you should always use AbstractBaseUser.
Note: It's also not a good practice to name same your models, django already has User model in the django.contrib.auth, so change its name.
So, you haven't specified the custom user model, so you should not able to authenticate, as by default authentication model is User which is at django.contrib.auth. So, with the current code when you make superuser through python manage.py createsuperuser and then you authenticate, so it will work.
You should use #login_required(login_url='login') instead of #login_required(redirect_field_name='login').
You need to correctly authenticate the user before logging in.
from django.contrib.auth import authenticate, login
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
More information in the documentation
Django version 3.2
I have created a AbstractUser model for storing info of Bank's Customer . I am able to register the customer with username and password . But it's not getting authenticated while login .
In admin page the password is saved as plain text , which is not expected . It should be saved in hashed form by default in Django .
Please give some directions to solve this . What I am doing wrong ?
In settings.py I have added line :
AUTH_USER_MODEL = 'banking.Customer'
models.py :
'''
This stores all customers of this bank .
'''
class Customer(AbstractUser):
#username = models.CharField(max_length=128, unique=True)
#first_name = models.CharField(max_length=128)
#last_name = models.CharField(max_length=128)
#email = models.CharField(max_length=128)
phone = models.CharField(max_length=128)
#password = models.CharField(max_length=2048)
dateJoined = models.DateTimeField(auto_now_add=True)
# completed, pending, blocked, error
verificationStatus = models.CharField(max_length=128)
#USERNAME_FIELD = 'username'
#REQUIRED_FIELDS = []
def __str__(self):
return f"{self.username}, {self.first_name} {self.last_name}, {self.email}, {self.password}"
views.py :
def register(request):
if request.method == "POST":
# get the information from form
print("POST request :" + str(request.POST))
userName = request.POST["userName"]
firstName = request.POST["firstName"]
lastName = request.POST["lastName"]
email = request.POST["email"]
phone = request.POST["phone"]
password = request.POST["password"]
# insert it in DB, keep in mind that username should be unique
try:
customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")
customer.save()
print("Database " + str(customer))
return HttpResponseRedirect(reverse('login'))
except:
# send register page agin with error message
context = {"message": userName + " userName is already taken ."}
return render(request, "banking/register.html", context)
else:
return render(request, "banking/register.html")
def login(request):
if request.method == "POST":
# get info from login form
username = request.POST["userName"]
password = request.POST["password"]
# check if user is valid
customer = None
try:
# check if userName exist in DB
print("check user")
customer = authenticate(request, username=username, password=password)
except:
customer = None
# save customer in session
if customer is not None:
login(request, customer)
return HttpResponseRedirect(reverse('mainPage'))
else:
# return to login page with error message
context = {"message": "Invalid credentials"}
return render(request, "banking/login.html", context)
else:
return render(request, "banking/login.html")
In your register() method of views.py, you have to edit your code to be:
customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, verificationStatus="verified")
customer.set_password(password)
customer.save()
While saving user, we have to set passwords using set_password() method, as it will save password using appropriate hash/encryption algorithm.
You create the customer by using the models __init__ method (the constructor):
customer = Customer(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")
But this does not consider the fact that the password needs to be hashed and saves the password as plain text. This causes your user to be unable to login as the authenticate function works on the premise that the password is hashed.
You should instead use the create_user [Django docs] method of the user model's manager, UserManager, which will automatically hash the password:
customer = Customer.objects.create_user(username=userName, first_name=firstName, last_name=lastName, email=email, phone=phone, password=password, verificationStatus="verified")
When creating the custom User class in Django, password encryption and saving mechanism should be handled by the Manager class.
See the code used from the EmployeeManager class in the astikgabani/Inventory-Management repository.
I am fairly new to Django so I wanted to know what should I do to make default authenticate function of Django accepts only email and password to login, assuming that in sign-up form I have both username and email. The following code does not work properly.However when I add
username = request.POST.get('username')
and change
user = authenticate(request, username=username email=email, password=password)
It logs in as expected.
The login View:
def LoginPage(request):
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
user = authenticate(request, email=email, password=password)
if user is not None:
login(request, user)
print('logged')
return redirect('/inker/')
return render(request, 'authy/login.html')
The sign up view:
def SignUpPage(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
return redirect('/login/')
context={'form':form}
return render(request, 'authy/signup.html', context)
The form module:
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username','email', 'password1', 'password2']
As you can see in Sign Up view we have both username and email but in login form I want it to just login user based on only email. How can I implement this.
Also how can I compact both username and email into one input when user wants to login? pretty much like instagram, facebook login page
If you just want to access user using email, you're not using authentication on the first place. So, to solve your purpose, following approaches can be followed:
Get user email in url params in every request (so that user can be identified)
Set default password while creating the user account for all users and use that password while authentication (not recommended)
I was creating a login and registration page for my project and was using the Django MySQL database for login and creating users the signup was done correctly but the login function is not working for me.
PS: The is_active is Set True but still this is not working
With all correct info, it shows None. I have given all the necessary parts of the file and codes
I tried everything but nothing seems to work also tried some of the solutions listed on StackOverflow but still, nothing worked for me.
from django.shortcuts import render, redirect
from .models import Description
from django.http import HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
# Create your views here.
def index(request):
d = Description.objects.all()
return render(request,'index.html',{'des':d})
def signup(request):
if request.method == 'POST':
first_name = request.POST['first']
last_name = request.POST['last']
user_name = request.POST['user']
email = request.POST['email']
pass1 = request.POST['password1']
pass2 = request.POST['password2']
if pass1 == pass2:
if User.objects.filter(email=email).exists():
print("Email taken")
elif User.objects.filter(username=user_name).exists():
print("Username taken")
else:
user = User.objects.create_user(username = user_name, first_name=first_name,last_name=last_name, password=pass1, email=email)
user.save()
print("User created")
else:
print("Password Not Matching")
return redirect('/')
else:
return render(request,'signup.html')
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
print(email,password)
user = authenticate(request, email=email, password=password)
print(user)
if user is not None:
login(request, user)
print("Logged in")
else:
print("not logged in")
return redirect('/')
else:
return HttpResponse("Invalid")
Django authenticate method allows for authenticating using only username.
You can get the user's username from the User model using the user's email
username = User.objects.get(email=email).username
password = request.POST.get('password')
Replace this user = authenticate(request, email=email, password=password)
with this user = authenticate(request, username=username, password=password)
The problem is django's default authentication mechanism don't allow you authenticate using email, you can only authenticate user using username .
either way, you can get the user's username from the User model using his email and then you can authenticate user.
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
username = ''
try:
username = User.objects.get(email=email).username
except User.DoesNotExist:
return HttpResponse("Invalid")
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
print("Logged in")
else:
print("not logged in")
return redirect('/')
else:
return HttpResponse("Invalid")
Also dont store password directly, always user standard set_password() function of django
if User.objects.filter(email=email).exists():
print("Email taken")
elif User.objects.filter(username=user_name).exists():
print("Username taken")
else:
user = User.objects.create_user(username = user_name, first_name=first_name,last_name=last_name, email=email)
user.set_password(pass1)
user.save()
print("User created")
The problem is your signup method. You should not give password to the init function. You should use User's set_password method.
In your sign_up view remove password=pass1 at the line where you are creating User object. And after that before saving the user, add user.set_password(pass1).
Hope this helps!
I have made custom forms for log in and registration in Django using HTML/CSS and not Django's form.as_p. I have the following code in views.py:
def login_user(request):
logout(request)
if request.POST:
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('/mainpage/')
else:
login_message = "Your username or password is incorrect."
return render(request, 'index.html', {'login_message': login_message})
return render(request, 'index.html')
def sign_up(request):
if request.POST:
username = request.POST['username']
email = request.POST['email']
password = request.POST['password']
password_confirm = request.POST['password-confirm']
if(valid_form(username, email, password, password_confirm)):
#create the new user
user = CustomUser(name=username, email=email, password=password)
user.save()
user = authenticate(username=username, password=password)
login(request, user)
return redirect('/mainpage/')
else:
message = "There was a problem."
return render(request, 'index.html', {'message': message})
return render(request, 'index.html')
I have the following model for CustomUser in models.py:
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200, null=True)
email = models.EmailField(max_length=70, null=True)
password = models.CharField(max_length=50, null=True)
My code is working for the sign up and I can create a new user after inputting the username, email and password. When I check the users in the user list on the Django admin site, for the new user I created (ruby), only their email is stored and not their username. I believe this is the reason I am also having trouble logging in with this new user.
However I am not sure why the username isn't being stored for the new user I created. Any insights are appreciated.
Probably the issue is here:
user = CustomUser(name=username, email=email, password=password) # <-- Here
user.save()
You are not storing the username here. I think its better to do it either:
user = CustomUser(name=username, email=email, username=username)
user.set_password(password) # otherwise the password will be stored in plain text
user.save()
Or you can use create_user manager method to create Users.
According to django doc https://docs.djangoproject.com/en/1.8/_modules/django/contrib/auth/models/, AbstractUser has username field which is required and used for authentication:
username = models.CharField(_('username'), max_length=30, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, digits and '
'#/./+/-/_ only.'),
validators=[
validators.RegexValidator(r'^[\w.#+-]+$',
_('Enter a valid username. '
'This value may contain only letters, numbers '
'and #/./+/-/_ characters.'), 'invalid'),
],
error_messages={
'unique': _("A user with that username already exists."),
})
In your case, you have a name field which is an additional field in the model, but in the views, you are passing username to name, while the required username field is not filled up.
Try to remove 'name' field in the model. Pass username to username
Since your 'CustomUser' class extends AbstractUser (which provides the full implementation of the default User as an abstract model), you should use the same signature (username, instead of name) as follows:
#create the new user
user = CustomUser(username=username, email=email, password=password)