I have a Django project in which I want to authenticate users against an Active Directory. Therefore, I am using the django-python3-ldap framework. I am able to sync users(./manage.py ldap_sync_users), grant superuser admin access, and login to the default Django admin page using the framework as backend. However, when I try to authenticate on my site, the user state remains AnonymousUser.
views.py
def login(request):
try:
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user, backend=django_python3_ldap)
context = {'user': user}
return render(request, 'website/home.html', context)
else:
context = {'': ''}
return render(request, 'website/login.html', context)
except:
print()
login.html
<!-- Main content -->
<section class="hero is-success is-fullheight">
<div class="hero-body">
<div class="container has-text-centered">
<div class="column is-4 is-offset-4">
<div class="box">
<figure class="avatar">
<img src="">
</figure>
<form method="post">
{% csrf_token %}
<div class="field">
<div class="control">
<input class="input is-large" type="text" placeholder="Username" autofocus="">
</div>
</div>
<div class="field">
<div class="control">
<input class="input is-large" type="password" placeholder="Password">
</div>
</div>
<div class="field">
<label class="checkbox">
<input type="checkbox">
Remember Me
</label>
</div>
<button class="button is-block is-danger is-info is-large is-fullwidth">Login</button>
{% endblock %}
</form>
</div>
</div>
</div>
</div>
</section>
imports
from django.contrib.auth import authenticate, login
import django_python3_ldap
backend
AUTHENTICATION_BACKENDS = ('django_python3_ldap.auth.LDAPBackend',)
urls.py
path('login', auth_views.login, {'template_name': 'website/login.html'}, name='login'),
I see possibly two issues the backend is not pointing to a valid backend. Also your try except is a bit dangerous please remove it. Unless you are testing never use a blank except. Use something like except Exception as e: print(e). The reason I say that is the blank except was hiding the invalid backend error.
login(request, user, backend=django_python3_ldap)
# Should be
login(request, user, backend=django_python3_ldap.auth.LDAPBackend)
Related
I've created a login page as a homepage and only by adding manually in Django administration can create a user. I didn't create a registration form and message error else statement in home viwes.py is working on the admin panel. If I login by user, I get CSRF token error
homepage
views.py
from django.shortcuts import redirect, render
from loginapp.models import Register
from django.contrib import messages
from django.contrib.auth import authenticate, login , logout
def home(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(request,username=username, password=password)
if user is not None:
login(request, user)
return render(request, "home.html")
else:
messages.error(request, "Bad Creds!!")
return redirect('/')
return render(request, "home.html")
login page views.py
def index(request):
return render(request, "index.html")
login page name as index.html
<form id="stripe-login" method="POST" action="{% url 'home' %}">
{% csrf_token %}
<div class="trick" style="padding-bottom: 10px;">
<input type="text" name="username" required>
<label for="email">Username</label>
</div>
<div class=" trick" style="padding-bottom:10px;">
<input type="password" name="password" required>
<label for="password">Password</label>
</div>
<div class="field" style="padding-bottom:10px; padding-top: 10px;">
<input type="submit" name="submit" value="Continue">
</div>
<div class="reset-pass" style="padding-top: 20px;">
Forgot your password?
</div>
<div class="footer-link text-light" style="padding-top:10px;">
<span>
Don't have an account?
<a href="{% url 'signup' %}">
Request for a new account
</a>
</span>
</div>
</form>
for creating user you must use
User.objects.create_user() method
Ex: User.objects.create_user(username=username,email=email,password=password)
I have created a new table using models.py and this table stores data to my models.py table which I created.
Now when I am going to my login page its not able to authenticate the details from that table and always gives invalid credentials.
My app name which I created is User and the table name which is stored in SQLite is User_register
Login.html
<div class="wrapper gradient">
<div class="container">
<div class="row centered-form">
<div class="col-xs-12 col-sm-8 col-md-4 col-sm-offset-2 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><center><b>Login To Web App!!</b></center> </h3>
</div>
<div class="panel-body">
<form role="form" method="POST">
{% csrf_token %}
<div class="form-group">
<input type="text" name="email" id="email" class="form-control input-sm" placeholder="Username">
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-sm" placeholder="Password">
</div>
<div class="form-group">
{% for message in messages %}
<p style="color:black;">{{message}}</p>
{% endfor %}
</div>
<input type="submit" value="Login" class="btn btn-info btn-block">
</form>
</div>
</div>
</div>
</div>
</div>
</div>
Models.py
class Register(models.Model):
first_name = models.CharField(max_length=90)
last_name = models.CharField(max_length=90)
email = models.EmailField(max_length=90)
password = models.CharField(max_length=90)
Views.py
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = auth.authenticate(email=email, password=password)
if user is not None:
auth.login(request, user)
return render(request,'index.html')
else:
messages.info(request, 'Invalid credentials')
return render(request,'login.html')
else:
return render(request, 'login.html')
I may be out of touch, but
the fields youre using are premade in the standard auth backend which you easily set to use those fields. A good tutorial for this is apart of this youtube series https://youtube.com/playlist?list=PLzMcBGfZo4-kQkZp-j9PNyKq7Yw5VYjq9
Or check out a extended example with password reset etc in the register app of this repo https://github.com/HarryLudemann/Job-Search
If you still require making your own custom model i suggest you using a 'custom authbackend' this is nearly always the way togo unless you use the prebuild form check it ou here https://docs.djangoproject.com/en/3.2/topics/auth/customizing/
If You still want to use the setuo youre using you should be using the built in forms, this allows you to use the cleaned_data method check out the docs https://docs.djangoproject.com/en/3.2/ref/forms/fields/
Or look for a example in the github repo above.
If this does not answer help please post any more code, errors or info you have. Also ensure you have run the makemigrations and migrate aswell as mugrate your server setup. Hope this somewhat helps 👍
When a new user signs up for an account, the admin panel shows that a password has not been set for the user (despite saving it via views.py). Another strange thing I noticed is that the password is being saved to the email field in the database. The code appears fine. Not sure where I went wrong. Any help would be greatly appreciated.
sign up html template
{% if user.is_authenticated %}
<h2>currently logged in as {{ user.username }} </h2>
{% else %}
<h1 class="h5 text-center">Create Account</h1>
<h4>{{ error }}</h4>
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" autocomplete="username" placeholder="Username" id="id_username" required>
</div>
<div class="form-group">
<label for="password1">Password</label>
<input type="password" class="form-control" name="password1" placeholder="Password" autocomplete="new-password" required id="id_password1">
<small>Password must be at least 8 characters</small>
</div>
<div class="form-group">
<label for="password2">Confirm Password</label>
<input type="password" class="form-control" name="password2" placeholder="Confirm Password" autocomplete="new-password" required id="id_password2">
</div>
<ul>
<li>Your password can’t be too similar to your other personal information.</li>
<li>Your password must contain at least 8 characters.</li>
<li>Your password can’t be a commonly used password.</li>
<li>Your password can’t be entirely numeric.</li>
</ul>
<!-- <div class="form-group">
<div class="custom-control custom-checkbox text-small">
<input type="checkbox" class="custom-control-input" id="sign-up-agree">
<label class="custom-control-label" for="sign-up-agree">I agree to the <a target="_blank" href="utility-legal-terms.html">Terms & Conditions</a>
</label>
</div>
</div> -->
<button class="btn btn-primary btn-block" type="submit">Create Account</button>
</form>
views.py
def signup(request):
if request.method == 'GET':
return render(request, 'events/signup.html', {'form': UserCreationForm()})
else:
# Create new user and profile
if request.POST['password1'] == request.POST['password2']:
try:
print(request.POST['password1'])
print(request.POST['password2'])
user = User.objects.create_user(request.POST['username'], request.POST['password1'])
user.save()
login(request, user)
return redirect('home')
except IntegrityError:
return render(request, 'events/signup.html', {'form': UserCreationForm(), 'error':'Username has already been taken. Please use a different name.'})
else:
# Tell the user the passwords don't match
return render(request, 'events/signup.html', {'form': UserCreationForm(), 'error':'Passwords did not match'})
There's no mention of "email" anywhere in the code but for some reason the password gets saved as email and the actual password isn't getting set.
You need to set password explicitly, or send it in the third param, second param of create_user method is email, thats why password is being set as email.
reference to set_password method
reference to create_user method
You need something like this.
user = User.objects.create_user(username=request.POST['username'])
user.set_password('new password')
user.save()
Your code:
user = User.objects.create_user(request.POST['username'], request.POST['password1'])
user.save()
See the the docs:
create_user(username, email=None, password=None, **extra_fields)
So, oops, you send the password as second argument and it is interpreted as being the email address.
create_user(username=request.POST['username'], password=request.POST['password1'])
Should work.
i have a html template which i want to use for authentication in django. I am using pymongo to connect to remote mongodb and fetch_data. The remote mongodb has a collection which has username & password for a demo user. I read that django has a inbuilt authentication module but i dont want to use that.
My template :
<form action="/index.html">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-user"></i></div>
<input type="text" class="form-control" placeholder="Username">
</div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-asterisk"></i></div>
<input type="password" class="form-control" placeholder="Password">
</div>
</div>
<div class="row">
<div class="col-xs-8 text-left checkbox">
<label class="form-checkbox form-icon">
<input type="checkbox"> Remember me
</label>
</div>
<div class="col-xs-4">
<div class="form-group text-right">
<button class="btn btn-success text-uppercase" type="submit">Sign In</button>
</div>
</div>
</div>
</form>
How can i pass data from my template to my views.py file? Currently I am not using any authentication.
my views.py:
from django.shortcuts import render
from django.http import HttpResponse
def login(request):
return render(request, 'login/login.html')
In Pymongo, I can use command db.getCollection('users').find({'email':'%s'}) {{email}} to pass email and verify.
PS: Most tutorial i read were about django's inbuilt authentication.
The generic way is to write custom authentication backend which handles authentication for you. Then it is recommended to create custom form which is rendered in your template.
Authentication backend
class YourBackend(object):
def authenticate(self, username=None, password=None):
# Check the username/password and return a User.
def get_user(self, user_id):
# return user by given user_id
Settings
When you have implemented your own authentication backend you should define it inside django settings.py. The first one is django's default authentication backend.
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'your.own.authentication.backed',
)
Form
from django import forms
class YourLoginForm(forms.Form):
username = forms.CharField(max_length=254)
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
View
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth import authenticate, get_backends
def login(request):
form = YourLoginForm(request.POST or None)
if form.method == 'POST':
if form.is_valid():
user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password'])
if user:
# redirect user to somewhere
return render(request, 'login/login.html')
Template
<form action="{% url 'your-login' %}" method="POST">
{{ form.non_field_errors }}
<div class="form-group">
<div class="input-group">
{{ form.username.errors }}
<div class="input-group-addon"><i class="fa fa-user"></i></div>
{{ form.username }}
</div>
</div>
<div class="form-group">
<div class="input-group">
{{ form.username.errors }}
<div class="input-group-addon"><i class="fa fa-asterisk"></i></div>
{{ form.password }}
</div>
</div>
<div class="row">
<div class="col-xs-4">
<div class="form-group text-right">
<button class="btn btn-success text-uppercase" type="submit">Sign In</button>
</div>
</div>
</div>
</form>
Urls
url(r'^login$', 'views.login', name='your-login'),
I suggest you to use external libraries for authentication and profiling. As I remember they have got options for mongodb. But if you want to reinvent the wheel, then you should use following.
1) Create class that extends form.ModelForm to handle registration and authentication process. You could read documentation how to do it. If will help you to handle validation of the data. You'll able to validate unique email fields and other stuff.
2) Create HTML form. You could use existing and just connect it with your ModelClass.
3) If you're using forms you could get data just with following command in yor controller:
form = MyForm(request.POST or None)
Then you'll be able to pass data to this form. If you don't want to use and form classes then you could retrieve if in such way in your controller:
if request.method == 'POST':
login = request.POST.get('login', None)
password = request.POST.get('password', None)
Assign controller with the form you could using urls.py, just the same way:
url(r'^login$', 'views.login', name='login'),
So using forms class you'll be able to pass empty form when GET request arrived and if it's POST request then you could collect data. Also, add to your HTML form following:
<form action="/login" method="post">
4) When you receive data from your login form you should authenticate. This could be done using custom authentication backend. You could find info here or just Google how to do it. I've never done it before, but it's pretty simple.
I'm making a webpage where I login and add people to an address book. Once I login and click on the "add address" button, I'm redirected back to the login page with the following url:
http://localhost:8000/xcard/login/?next=/xcard/add_address/
If I login again I can get to account page, address book, and then add_address book page without being caught in the login loop. I can logout and login and add addresses without relogin in twice. But the first time I ever login I have to do it twice. Not sure if it's a problem with the login or the add address code.
Views.py
class LoginView(View):
def get(self, request):
''' if user is authenticated '''
if request.user.is_authenticated():
return render(request, 'xcard/account.html')
else:
return render(request, 'xcard/login.html')
def post(self, request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
state = "The email or password is incorrect"
if user is not None:
login(request, user)
return HttpResponseRedirect('/xcard/account/')
else:
return render(request, 'xcard/login.html', {'state':state})
class AddAddressView(View):
def get(self,request):
address_form = AddressForm()
friend_form = FriendForm()
return render(request, 'xcard/add_address.html', {'friend_form':friend_form, 'address_form':address_form})
def post(self,request):
address_form = AddressForm(request.POST)
friend_form = FriendForm(request.POST)
if address_form.is_valid() and friend_form.is_valid():
new_address = address_form.save()
new_friend = friend_form.save(commit=False)
new_friend.address = new_address
new_friend.save()
return HttpResponseRedirect('/xcard/address_book')
else:
return render(request, 'xcard/add_address.html', {'state' : "Failed", 'friend_form':friend_form, 'address_form':address_form})
Templates:
address_book.html
{% include "xcard/header.html" %}
{% block main %}
<div class="container">
<h3 class="text-info"><u>Your Account</u></h3>
Add
Import
</div>
{% endblock %}
Templates:
login.html
{% extends "xcard/base.html" %}
{% block main %}
<div class="container">
<div class="row space">
<p class="text-center lead text-warning">
Login page</p>
<p class="text-center text-info">Trusted worldwide!</p>
</div>
<div class="row">
<div class="span offset4">
<form class="well" action="/xcard/login/" method="post">
{% csrf_token %}
<p class="lead">Sign In</p>
<fieldset class="login_page">
<p class="text-error"><strong>{{ state }}</strong></p>
<label class="control-label" for ="inputIcon">Email</label>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-user"></i></span>
<input type="text" class="span3" id="ernainputIcon" required name="username" placeholder="Username...."/><br/><br/>
</div>
</div>
<label>Password</label>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-lock"></i></span>
<input type="password" class="span3" id="inputIcon" required name="password" placeholder="Password...."/><br/><br/><br />
</div>
</div>
<button class="btn btn-primary">Sign In</button>
Not a user?
Sign up
</fieldset>
</form>
</div>
</div>
</div>
{% endblock %}
I just found this in my urls.py
url(r'^add_address/$', login_required(AddAddressView.as_view(), login_url='/xcard/login/')),
Maybe this is causing the problem? But why doesn't it register that I'm already logged in?
first do the correction in AddAddressView function. update line
return render(request, 'xcard/add_address.html', {'friend_form':friend_form, 'address_form':address_form})
it will work
This was my solution - logout before you try to authenticate.
This issue happened to me when users were logging in and logging back in with a different username.
import django.contrib.auth as djangoAuth
djangoAuth.logout(request) # logout
user = djangoAuth.authenticate(username=username, password=password) # login