In my project I have an existing legacy database, so I use inspectdb to create models and for specific requirements I am using custom user model
No when I create a user directly in the DB using SQL commands then the user gets authenticate and is able to login, but when I create user using SHELL commands (model_name.objects.create()), then the user is not authenticated and is not able to login.
and the main point, ** when I create user using SQL command password is stored in RAW form, but when I create user using SHELL commands the password looks like
"pbkdf2_sha256---------------------------------"
managers.py
#managers.py
class UsermanagementCustomUserManager(BaseUserManager):
def create_user(self,emailid,firstname, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not emailid:
raise ValueError('Users must have an email address')
user = self.model(
emailid=self.normalize_email(emailid),
password=password,
)
user.set_password(password)
user.save(using=self._db)
return user
backends.py
#backends.py
from django.contrib.auth.backends import BaseBackend
from django.contrib.auth.hashers import make_password,check_password
from django.contrib.auth import get_user_model
Usermanagement = get_user_model()
class EmailAuthBackend(BaseBackend):
def authenticate(self,request,username=None,password=None):
# print("Custom authenticate rqst: ",request)
try:
print("Trying the email backend!")
user = Usermanagement.objects.get(emailid=username)
print("Got the user")
# print(password)
# print(user.password)
# print(check_password(password))
# print(user.check_password(password))
if user.password == password or user.check_password(password):
return user
except user.DoesNotExist:
return None
def get_user(self,user_id):
try:
print("Getting the user of the Email Bkacned")
return Usermanagement.objects.get(pk=user_id)
except Usermanagement.DoesNotExist:
return None
views.py
#views.py
from django.contrib.auth import login,logout ,authenticate
from django.contrib.auth.forms import AuthenticationForm
def loginPage(request):
# POST
if request.method == 'POST':
form = AuthenticationForm(request,data=request.POST)
if form.is_valid():
email = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
#Check
print("EMAIL: ",email)
print("PASSWORD: ",password)
# Authentication USER
user = authenticate(request,username=email,password=password)
print("Authenticated ",user) # Check
# check
print(user)
if user is not None:
if user.is_active:
login(request,user,backend='accounts.backends.EmailAuthBackend')
# messages.info(request, f"You are now logged in as {email}.")
return redirect("home")
else:
pass
else: # If User Not found
# messages.error(request,"User not found")
# return HttpResponse("User not found, not able to login")
pass
else: # Form InValid
# messages.error(request,"Invalid username or password.")
# return HttpResponse("Form Invalid")
context = {
"form" : form
}
return render(request,"loginPage.html",context=context)
# GET
else:
form = AuthenticationForm()
context = {"form":form}
return render(request,"loginPage.html",context=context)
The way I am authenticating my user is directly using
user.password == password
Related
I am using django contrip auth for authenticate user. Signup function always working and register and login user successfully but after that I m logged out and try to login again but this time login function doesnt work.
I add this codes my settings file
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
AUTH_USER_MODEL = 'app.User'
My User model seems like that in models.py
class User(AbstractUser):
pass
My Login and Register function
def dlogin(request):
if request.method=='GET':
return render(request, "login.html")
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
# Attempt to sign user in
user = authenticate(request, username=username, password=password)
print(user)
# Check if authentication successful
if user is not None:
login(request, user)
cur_user = request.user
return render(request,'index.html',{
'success':'login successful',
'user':cur_user
})
else:
return render(request,'login.html',{
'error':'Invalid username and/or password.'
})
#csrf_exempt
def signup(request):
if request.method != "POST":
return render(request, 'signup.html')
# Get form information
username = request.POST["username"]
password = request.POST["password"]
confirmation = request.POST["confirmation"]
# Ensure password matches confirmation
if password != confirmation:
return render(request,'register.html',{
'message':'Passwords dont match'
})
# Attempt to create new user
user = User.objects.create_user(username,password)
user.save()
login(request, user)
return redirect('index')
I did some research and couldn't find any problem in my code. Does anyone can help me?
I fixed it
I change this in signup function
user = User.objects.create_user(username,password)
to this
user = User.objects.create_user(username=username,password=password)
and it works but i dont know why
I am trying to understand login methods in Django. So because I want to login with email not username. I wrote a custom authentication backend and exposed it in settings.py
AUTHENTICATION_BACKENDS = (
'accounts.backend.EmailAuthenticationBackend',
'django.contrib.auth.backends.ModelBackend',
)
class EmailAuthenticationBackend(ModelBackend):
def authenticate(self, request, email=None, password=None, **kwargs):
try:
user = Account.objects.get(email=email)
if user.check_password(password):
return user
except user.DoesNotExist:
pass
And in view user_login how I authenticate the user. And it's actually works. I mean kind of...
def user_login(request):
next = request.GET.get("next")
form = UserLoginForm(request.POST or None)
if form.is_valid():
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(email=email, password=password)
login(request, user)
if next:
return redirect(next)
return redirect("/")
context = {
"form": form
}
return render(request, "accounts/user_login.html", context)
the authenticate() method is returns the user. But redirect() is not working because in browser thinks user not logged in. I am not sure about how to handle the session part.
and custom UserLoginForm
class UserLoginForm(forms.Form):
email = forms.CharField()
password = forms.CharField()
def clean(self, *args, **kwargs):
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
if email and password:
user = authenticate(email=email, password=password)
if not user:
raise forms.ValidationError("user not exist")
if not user.check_password(password):
raise forms.ValidationError("incorrect password")
return super(UserLoginForm, self).clean(*args, **kwargs)
The second issue is if email or password wrong. it doesn't raise any error.
what is the best common way to handle custom login with email.
I think the reason, it doesn't redirect is you've assigned the
request.GET.get("next") into nxt variable, however you are
checking the next variable for redirecting, probably you should
change the variable nxt to next.
The reason that it doesn't raise any error is, you've put try and except to handle the thrown errors in the authenticate() method and you just put pass in the excpetion part. If you want the error to be thrown, just remove the try and except part from authenticate().
I am trying to achieve a login functionality like so that users can log into using their Email or Phone number or it's username as well but Django provides only email field in it's User model so that I've created an another model with One-To-One-Relation to User model and provided the phone number column but now I don't know how to achieve such functionality which I mentioned earlier.
my models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_type = models.IntegerField(choices=USER_TYPE, default=3)
mobile = models.BigIntegerField(unique=True)
my views.py
(I know it's a mess but I can't figure out how to have such functionality)
def login(request):
if request.method == "POST":
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
messages.success(request, 'You are logged in successfully!')
return redirect('/dashboard')
else:
user = auth.authenticate(profile_phone=username, password=password)
if user is not None:
auth.login(request, user)
messages.success(request, 'You are logged in successfully!')
return redirect('/dashboard')
else:
user = auth.authenticate(email=username, password=password)
if user is not None:
auth.login(request, user)
messages.success(request, 'You are logged in successfully!')
return redirect('/dashboard')
else:
messages.error(request, 'Invalid username or password')
return redirect('/login')
else:
if request.user.is_authenticated:
messages.success(request, 'You are already logged in')
return redirect("/dashboard")
return render(request, "accounts/login.html")
It is not true that the Django user model only provides an email field. It also has a username field as you want. Check documentation here. If you want to add a phone number or another field, you can implement like this:
from django.contrib.auth.models import User
class MyUser(User):
user_type = models.IntegerField(choices=USER_TYPE, default=3)
mobile = models.BigIntegerField(unique=True)
and the class will include everything that the base User model has.
Also, Django provides a built-in login method that you can also use. Check this tutorial.
Apologies if this is simple or my terminology is off, this is my first django project. I haven't been able to find a similar solution for this online.
I have an existing application, with a postgres DB where I authenticate my users. I have wrote an application in Django to interact with some tables and display info to the user. I would like to use Django to login and track User sessions against this DB. so I can use the features like
{% if user.is_authenticated %}
but I don't want to use the migrate command so I don't want to change the existing DB. I can access the table where the account info is as I created a model for it.
I see you can use remote user logon param but I cant find any sample or guide on how to use it and am completely lost.
Right now I create a login form in the views page. Then get the username and password that is entered, but I don't know what to do next. Also would need to hash the password. Is there a libray in djano that will do that for the app.
Any pointers or online guides for this would be appreciated.
Here is the views for login
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
email = form.data['account_email']
password = form.data['account_password']
user = authenticate(username=email)
if user.check_password(password):
login(request, user)
return redirect('myapp:cust_select')
else:
# Username and password did not match
raise ValidationError('Invalid Username/Password')
return render(request, 'myapp/login.html', {'form' : form}
backends.py
from django.conf import settings
from django.contrib.auth import get_user_model
class UserAuthBackend(object):
def authenticate(self, username=None, password=None):
try:
account = get_user_model()
user = account.objects.get(account_email=username)
if user:
return user
except account.DoesNotExist:
print "account not found"
return None
def get_user(self, user_id):
try:
account = get_user_model()
return account.objects.get(pk=user_id)
except User.DoesNotExist:
return None
models.py
class Accounts(AbstractUser):
account_id = models.AutoField(primary_key=True)
account_email = models.CharField(max_length=100)
account_password = models.CharField(max_length=20)
def __str__(self):
return self.account_email
class Meta:
managed = False
db_table = 'accounts'
settings.py
AUTHENTICATION_BACKENDS = ( 'myapp.backends.UserAuthBackend', )
Its keeps exiting with the same error in the sql query.
column accounts.password does not exist
LINE 1: SELECT "accounts"."password", "accounts"."last_login", "acco...
It doesnt appear to be using my Account model. It does select it from that table but how can i get it to stop requesting accounts.password and accounts.last_login as they dont exist in y Accounts model
For reference
Note: You need to do try, catch to get this code working
def login(request):
form = LoginForm()
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
username = form.data['account_email']
password = form.data['account_password']
# First authenticate
user = authenticate(request, username=username, password=password)
if user is not None :
# Succeed, now log user in
login(request,user)
return redirect('myapp:select')
else:
# Username and password did not match
raise ValidationError('Invalid Username/Password')
return render(request, 'myapp/login.html', {'form' : form})
I'm using Django 1.11 and views based on classes.
My user model is customized and it has a status field where it has "enabled, blocked and disabled". I'd like to know how I can only allow users to log in and the others are barred.
Thanks!
you can override default form,
forms.py
from django.contrib.auth.forms import AuthenticationForm
class AuthenticationFormWithChekUsersStatus(AuthenticationForm):
def confirm_login_allowed(self, user):
if not user.status == 'enabled':
raise forms.ValidationError(
("Your account has disabled."),
code='inactive',
)
the docs: AuthenticationForm
And in your urls, it can be like:
from forms import AuthenticationFormWithChekUsersStatus
url(
r'^login/$', auth_views.LoginView.as_view(
authentication_form=AuthenticationFormWithChekUsersStatus
)
)
more details: all-authentication-views
You can do the following to check if user status is enabled
from django.views.generic import View
class LoginView(View):
def post(self, request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.status == 'enabled': # checking if user is "enabled"
login(request, user)
return HttpResponseRedirect('/form')
else:
return HttpResponse("Disabled user.")
else:
return HttpResponseRedirect(settings.LOGIN_URL)
return render(request, "index.html")