Django authenticate not keeping user logged in - python

I am attempting to learn Django's authentication system by contriving a basic login scenario. My views are set up such that a view, logIn, either receives a user's credentials (and prints the success/failure of the login), or it renders a login form.
A second view, privatePage, is designed as a sanity check that the user is actually logged in. The code is as follows:
views.py:
#login_required(login_url='/logIn')
def privatePage(request):
return HttpResponse("You're viewing a private page")
#csrf_exempt
def logIn(request):
if request.method == "POST" and \
request.POST.get('email') and \
request.POST.get('password'):
user = authenticate(username=request.POST['email'],
password=request.POST['password'])
return HttpResponse('Valid login' if user is not None else 'Invalid login')
# render login form
return HttpResponse("<form>...</form>")
I'm finding that after succcessfully logging in via the logIn view, I am still redirected to the login view upon trying to visit privatePage. FYI, I'm attempting to visit the privatePage view directly by URL, as opposed to navigating through provided links (e.g. I'm not sure if I'm violating some CSRF rule).
Any idea what's going on?

You've not actually logged in. You need to login the user after verifying their identity with authenticate:
from django.contrib.auth import login
user = authenticate(email=email, password=password)
if user is not None:
login(request, user)
login should only be used on users that have been confirmed to exist.
What authenticate does:
verifies a user is who they claim to be
It does not perform the actual login.

To keep the user logged in a session must be provided to user with usage of login() method. Login is the process of providing user with a session and authenticate() verifies that the given credentials corresponds to an existing user model object in database . Import django's built in login and authenticate methods from django.contrib.auth import authenticate, login. And then your code looks like
user =authenticate(email, password)
If user:
login(user, request)
Hope it helps :)

Related

How can I pass the request if I redirect and then render the template

I have a requirement, from login page jump to the admin page, you know the URL address should change to the admin page.
If I only use render to admin page, the URL address will not change, so in this post I get the OptimusCrime's good answer.
But if I redirect and then render template, I can not pass the request from login page to the admin page.
in the login page's views.py:
...
return redirect('/app_admin/index/')
in the admin page's views.py:
...
return render(request, 'app_admin/index.html') # there the request is None.
How can I pass the request to the admin page's views.py?
You should take a look at some basic Django tutorials, such as this one, which describes how to create a login handler.
The gist is this:
In the view where the user submit the form, you evaluate the username and/or password. If the submitted the correct information (username and password), then save this information in the session. Redirect the user to the logged in (restricted) area and check the session. If the session has the correct information, then allow the user to view the content, otherwise redirect the user out.
Simple login logic (illustrative):
def login(request):
m = Member.objects.get(username=request.POST['username'])
if m.password == request.POST['password']:
# Username and password is correct, save that the user is logged in in the session variable
request.session['logged_in'] = True
request.session['username'] = request.POST['password']
# Redirect the user to the admin page
return redirect('/app_admin/index/')
else:
# Username and/or password was incorrect
return HttpResponse("Your username and password didn't match.")
Simple admin page logic (illustrative):
def admin_index(request):
# Make sure that the user is logged in
if 'logged_in' in request.session and request.session['logged_in']:
# User is logged in, display the admin page
return render(
request,
'app_admin/index.html',
{'username': request.session['username']}
) # You can now use {{ username }} in your view
# User is not logged in and should not be here. Display error message or redirect the user to the login page
return HttpResponse("You are not logged in")
Note that these are two different views (and URLs), that you have to map up in your urlpatterns.

Using the django authentication system

I want to login with handler.
I have a code use session but i want to use handler:
I have visit :
https://docs.djangoproject.com/en/1.11/topics/auth/default/
But i don't understand complete.
I want to log user (with username or email and password)
Do you have a code for example or project in stackoverflow or github or . . . ???
login the user is easy if you are using default user model from django.contrib.auth.models
from django.contrib.auth import authenticate, login
def user_login(request):
# check here that request.method is POST or not.
user = authenticate(username=request.POST.get('username'), password=request.POST.get('password'))
if user is not None:
login(request, user)
# send some http response here that login successful or redirect to some other page
else:
# return an error page saying that username password not correct
authenticate function will check for username and password in User table in the database if it founds a user matching query then it returns the user object else it will return None. You might not want to manage sessions as django already sets a cookie for every user that successfully logs in so if user has logged in once then he will not be required to enter password again.

Django- why inbuilt auth login function not passing info about user to after successful login url

Hi I used the django inbult auth urls and views for my project and now have finished the initial user account creation/login/reset password process.
Now, the user can log in and be redirected to the after successful login url accounts/profile/.
I have several doubts on the django login function. For convenience, I've copy paste the django inbuilt login function code below.
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(request, data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
My questions are:
1 Is the REDIRECT_FIELD_NAME in the function set as '/profile/' in django.contrib.auth ?
I could see this variable is imported from django.contrib.auth
from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, logout as auth_logout, get_user_model
I don't have any setting for this variable, but after user successfully logged in, the page will be directed to /accounts/profile/
2 Has the login function passed the account info about the user? If yes, how can I access it?
From the code, if user successfully logged in, page will be redirected: return HttpResponseRedirect(redirect_to)
in my case, redirected to accounts/profile/ , initially the view for the url was simply a
HttpResponse("You have logged in successfully")
now when I am trying to implement the view function, I realize that no info about the user has been passed.
I've tried to print request in the view function, but there is no info about the user in the message printed in the server terminal, all I get is a long list of system settings or other info. However, the login should pass the info of who has just successfully logged in to the successful log in urls right?
Thank you very much for explaining.
After the login, you can access the user info by referring request.user in views and just {{user}} in templates. All you need to make sure is you're passing the RequestContext in the HttpResponse for the future request.
Yes, REDIRECT_FIELD_NAME is defined in __init__.py of django.contrib.auth which is simply a "next" what you passed from the login form.
In Django, there are more than one ways to force a user to login. By decorating a view function with #login_required, by calling the build-in login view for an user defined URL and etc., Refer about the login settings variables here. You'll get some more ideas.
Building custom login page. That link gives you an example for custom login implementaion. Consider you have decorated a view with #login_required and it's corresponding URL is /login_test/. Then the {{next}} context variable in the login form will be rendered with /login_test/. So after you login,
<input type="hidden" name="next" value="{{ next }}" />
This element's value will be taken for redirecting as per the REDIRECT_FIELD_NAME. Though I suspect that that example is missing the setting of settings.LOGIN_URL to the URL login/. Never mind, it's being passed as an argument in the decorator itself.
To override this behavior just put following in settings.py of your app :
LOGIN_REDIRECT_URL = "/"
This will redirect to your home page. You can change this url to preferred url.
Once the user is redirected to accounts/profile/ the view for that link will be returned. You can access information about the currently logged in user there as per this post by using request.user. Also tip to see what information you have access to in your views. Use import pbd; pdb.set_trace(). This pops you into a python prompt with access to all of the current variables. To see all the defined variables call locals(), though this will print out a ton of junk along with it. In the template you can display a "you can't access this page" message if the user isn't logged in.

'AnonymousUser' object has no attribute 'backend'

Using django-socialregistration, got following error:
'AnonymousUser' object has no attribute 'backend'
How,
I click on facebook connect url.
That took me Facebook and ask me to login. So I did, asked permission, I granted.
After that it redirect me to my site. And ask to setup. I provide user and email address.
Once I submit, got error like above:
Trace point:
path/to_file/socialregistration/views.py in post
128. self.login(request, user)
Do anybody know, what's wrong?
Oh man i used to get this error all the time, basically you are calling
self.login(request, user)
without calling
authenticate(username=user, password=pwd)
first
when you call authenticate, django sets the backend attribute on the user, noting which backend to use, see here for more details
https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.authenticate
I had the same error for a newly registering user.
def attempt_login(self, email, password):
user = authenticate(username=email, password=password)
login(self.request, user)
return user
I checked into database and the User has been created after registration, but this error was still there.
I figured out - user's login ( email ) was longer than 30 characters, and the form field had no validation. The username would get truncated in the database, and therefore authenticate was called for non-existent login.
254 - character is the advised length of email field.
Solution: emailfield-max_length-r11092.patch
I just got this error and found this post.. My solution was in the case was in the registration process. When the user was registering, my api and serializer wasn't hashing the password.. So in the api_view i had to manually hash the password like this..
from django.contrib.auth.hashers import make_password
# In the register api..
#ensure_csrf_cookie
#api_view(['POST'])
def register_api(request):
# Anywhere before the serializer
request.DATA['password'] = make_password(request.DATA['password'])
# Then the serializer
serializer = RegisterSerializer(data=request.DATA)
# ... etc.. Note that if you want to login after register you will have
# to store the initial password is some buffer because.. authentication
# the none hashed version.. then
authenticate(username=request.DATA['username'], password=someBuffer)
Hope that helps someone..

Django login using custom backend

I am working on a store based authentication system using Django, i am trying to make it so that the url is the one that specifies which store the user is trying to log in. Ex
login/store-name
then login the user in to the requested store. My question is, is there a way to do this using django's built in login form/mechanism or would i have to create my own login form and view.
In my opinion you should create your own form and login view:
from django.contrib.auth import authenticate, login
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active *** and user can login in this store ***:
login(request, user)
# Redirect to a success page.
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.
"and user can login in this store": get path from request and check it.
I think you could do this just in urls.py
urlpatterns = patterns('',
url(r'^login/store-name-1/$', login, name="login"),
url(r'^login/store-name-2/$', login, name="login"),
url(r'^accounts/logout/$', logout, {'next_page': '/',}, name='logout')
)
I'm not exactly clear on what you want to do?
If you want separate logins for each store, you will need to customize the login form, since the django auth package will create users that are universal to all of your stores.

Categories