Our DjangoCMS site is accessible via http and https.
Anonymous usage via http is ok. But I want to disable logins via http.
Is there a way to force the usage of https as soon as the user wants to login?
Even the login-page (with username and password fields) should not be available via http.
Background: I don't want the password to go over the wire unencrypted.
Update: The site gets hosted on an apache web server.
As I already mentioned it in the comments I strongly suggest you to NOT only serve the login page via https
.
Doing so just hides the fact that for example session information and authentication data is still transfered on the other requests unencrypted via http
. Your site will not be secure at all.
You're just pseudo-securing stuff so it's fancy to somebodys eye. It's just like using the password 12345
.
So please serve your website over https
to the user. A small guide, for nginx or apache2, on how to redirect your traffic from http
to https
can be found here:
As you've accepted in the comments, pushing all traffic to HTTPS is the best solution these days. If you only authenticate via SSL, you'll need to consider encryption/security in everything you write moving forward rather than it just being the default.
So in your server config, force all traffic to port 443. Assuming you're using apache you'd do this;
<VirtualHost *:80>
ServerName www.example.com
Redirect / https://www.example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName www.example.com
# ... SSL configuration goes here
</VirtualHost>
Then in your Django settings turn on secure cookies;
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
As a side note, Django has a setting to redirect HTTP traffic to HTTPS which is SECURE_SSL_REDIRECT
, but if you're doing this at the apache/nginx level you don't need to worry. For some further reading on SSL/HTTPS have a look here; https://docs.djangoproject.com/en/1.11/topics/security/#ssl-https
Django request has a is_secure()
You can check it in the view and redirect if not is secure:
if not request.is_secure():
return redirect("https://www.yourdomain.com/login")
@user1 has the logic right and you should serve your site through https in order to have it safe.
But in order to answer your exact question:
As shown here: How to know using Django if server is secure (uses https) and as @Zartch mentions in his answer, you should use the is_secure()
HTTPRequest method to check if your request is coming through https.
In order to use is_secure()
you need to check an incoming request
to your views:
def my_login_view(request):
if request.is_secure():
Do loggin
else:
Don't login
Now you can protect your other views with the login_required
decorator:
@login_required(login_url='/your/login/url')
def protected_view(request):
...
Personal suggestion: I use Django Rest Framework extensively and I would suggest it, in your case, because it has an isAuthenticatedOrReadOnly
permission class which you will like:
class MyLoginView(ObtainAuthToken):
"""
Login view for token-based authentication
"""
def post(self, request, *args, **kwargs):
if request.is_secure():
super().post(request, *args, **kwargs)
else:
Probably some redirect goes here...
Then in any other view or class-based view:
class MyOtherView(generics.GenericAPIView):
authentication_classes = (TokenAuthentication,)
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
...
The above will ensure that your users can login only through https and if they are not logged in they will only see a read-only view.
Give it a try if you like.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With