My website use to login function of django.contrib.auth.views.login.
But, some pages has problems about getting user information.
I tried to request.user & request.user.is_authenticated(). then request.user = "admin"(ok) but, request.user.is_authenticated() = guest..
And, Staying logged in After close browser.
what is problem?
Thank you.
If some pages will not show {{ user }} but others will, you're most likely not using RequestContext in the views where the user isn't available.
You can use a function like django's render shortcut to automatically use RequestContext.
As for the user staying logged in after closing the browser - that's normal. Your user is identified by a cookie that sits on your browser and is persistent.
Related
The admin app in django has this behaviour, and I want to replicate it in my project.
In the admin, once you login and press the browser back button, shows the home page again, and the it does not let you go back any further.
It doesn't seem it uses javascript.
Any ideas how to accomplish this?
Thanks.
My code
def login_user(request):
if request.user.is_authenticated:
return redirect(reverse('sinapsis-home'))
else:
...# code processing the authentication
# the redirect
return redirect(reverse('sinapsis-home'))
The solution is partially the proposed answer, but adding a cache decorator.
It is not javascript, and it was so easy to prove just disabling javascript in the browser. I was slow on that point.
As you navigate the browser back and for, the cached page does not load again, that's why you can go back, in this case, to the login page even if you are logged in. I think this behaviour is prone to problems, for example a csrf error. I repeat, not permitting the user go back to the login page once logged in is a standard behaviour of web apps, including the django admin.
So the solution to this problem is adding to the login view a redirect if the user is logged in and a never_cache decorator:
from django.views.decorators.cache import never_cache
#never_cache
def login_user(request):
...
if user.is_authenticated:
return HttpResponseRedirect(reverse('my_redirect'))
...
Well, Like you said that isn't js, It's as simple as an if conditional like:
if not request.user.is_authenticated:
# Return a login form to login
else:
return redirect('success:page')
Edit:
After add your code, the problem was that you were using request.user.is_autenticated() with parentheses and it was deprecated in Django 1.10 more information
I have a view that looks something like this simplified example:
#decorators.login_required()
def add_data(request):
some_value = request.POST['some_value']
# do stuff.
If a user is authenticated already, this completes successfully. If the user is not authenticated, this redirects to the login page. After the login page, the POST request is sent back to my add_data view is missing some_value and all other POST data.
Is this expected? Is there a way to access the POST data?
I am using the default django.contrib.auth.views.login. I have a custom login.html.
Is this expected?
Yes.
Is there a way to access the POST data?
Probably not, the anonymous user and logged in user will have separate sessions so that won't work.
You might be able to some how store the data in a GET variable and pass it to the login form, and then inspect that.
I'd suggest its just a case where the user has messed up, and they should check they are logged in before submitting things.
When a user requests a password reset, he will be redirected to /password/reset/done/ which tells the user that 'We have sent you an e-mail...', but if you directly go to that page, you get the same information, which is a little bit confusing since no email's sent to anyone.
Is there a variable which can be used in password_reset_done.html template like {{ messages }} so that with if conditions other content can show up for direct visitors? If not, is there a way to do this?
EDIT:
Please don't be hasty on labeling this as a duplicate question of How to use the built-in 'password_reset' view in Django?.
I do know how to show up that page /password/reset/done/, which is basically a stage specifically used for telling a user that "we've sent you an email so that you can follow the link to reset your password...", while the question you are refering to is about how to correctly redirect a user when password reset is successful.
What I'm looking for is a way to either rediret it to another page or show some different stuff when a user is trying to directly surf that page(well people do that sometimes) which is supposed to be viewed after he successfully submitted a password reset request. I need some kind of hook to make it work.
After checking into the codes in /account/views.py, I realized a message need to be added in previous /password/reset/ page so that it can be used in the next page which is /password/reset/done/.
Here's an example:
Add this in the form_valid method of class PasswordResetView:
get_adapter().add_message(self.request,
messages.INFO,
'account/messages/'
'password_reset_mail_sent.txt',
{'email': form.cleaned_data["email"]})
Now I can use {{ email }} in 'account/messages/password_reset_mail_sent.txt', and with {% if messages %} in password_reset_done.html I can serve direct visitors a different content.
You can use Django Messages Framework to notify the user with success or fail:
from django.contrib import messages
def my_view(request):
# your view logic goes here
if sucess_condition:
messages.success(request, 'Action accomplished with success.')
else:
messages.error(request, 'Action Failed.')
Check Messages Framework documentation for more details and customization.
i've recently implemented a simple change password view in my django project. The thing is that the old session should be destroyed for security reasons. What's the best way of doing this without asking the user to log in again.
I think i could just logout/login him/her, something like this:
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
#login_required
def change_password(request):
# My stuff
request.user.set_password(new_password)
request.user.save()
# I need this:
logout(request)
login(request,request.user)
But i think this is not the best idea. What do you think?
Is there another way to do this?
Am I missing something? (I mean, is this secure)
Take a look at this app https://github.com/atugushev/django-password-session.
This package makes invalidated all sessions (except a current session) after change a password.
Also this feature finally was implemented in Django 1.7. See: https://docs.djangoproject.com/en/dev/topics/auth/default/#session-invalidation-on-password-change
I just found out that this is now a built-in feature of Django, and has been since 1.7:
https://docs.djangoproject.com/en/1.7/topics/auth/default/#session-invalidation-on-password-change
Essentially, all sessions now include a hash of the users' password, so if the user ever changes their password, all their existing sessions are automatically invalidated.
So, the short answer to your question is: upgrade django.
One possibly undesirable side effect of this change is that, by default, a user ends up having to log in again as soon as they change their password. So you probably actually want the current user session to stay logged in. See the docs already linked, Django's built-in views for password change do that for you default, or you can manually call a function called update_session_auth_hash
django clears the session on logout so you will be fine:
https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.logout
When you call logout(), the session data for the current request is completely cleaned out. All existing data is removed. This is to prevent another person from using the same Web browser to log in and have access to the previous user's session data.
I don't understand whats are these security reasons that forces to reset session. But, the way is:
#login_required
def change_password(request):
request.user.set_password(new_password)
request.user.save()
username = request.user.username
logout(request)
user = authenticate(username=username, password=new_password) #<-- here!!
if user is not None:
login(request,user)
else:
#raise your exception
you should authenticate before login. Quoting doc:
Calling authenticate() first When you're manually logging a user in,
you must call authenticate() before you call login(). authenticate()
sets an attribute on the User noting which authentication backend
successfully authenticated that user (see the backends documentation
for details), and this information is needed later during the login
process.
I'm playing around with django and built a small app where a user can access their info via the url http:///localhost:8000/username/info/ . I want to add the ability to edit that info through http:///localhost:8000/username/info/edit/, but also want to make sure the currently logged in user (using django.contrib.auth) can access only his information. I accomplished this by doing the following in the view (username in the view args is captured from the url):
#login_required
def edit_info(request, username=''):
if request.user.username == username:
# allow accessing and editing the info..
else:
# redirect to some error page
So, obviously, I don't want user 'johnny' to edit the info belonging to user 'jimmy' by simply pointing his browser to /jimmy/info/edit/. The above works, but my concern is that I'm missing something here as far as security goes. Is this the right way to go about this?
Thanks.
This should work for what you are trying to do without any glaring security risks.
But, why show their username if no one else can see at least a profile or something at this location though? Wouldn't this be more like a 'account' page? Then you wouldn't check against the username in the url, the only url you could go to would be account, and it would just load the logged in user's info.
With the #login_required and parsing the request.user they will never end up on anothers profile. My profile view
#login_required
def user_profile(request):
""" User profile page """
u = User.objects.get(pk=request.user.pk)
return render_to_response('myapp/user_profile.html', {
'user': request.user,
})
Then in the template simply use stuff like:
Welcome <b>{{ user.first_name }} {{ user.last_name }}</b>