{"componentChunkName":"component---src-templates-blog-post-js","path":"/adding-security-to-your-website-via-a-user-login-system-2560f33dbf05440e9944dd21c5f26b82/","result":{"data":{"site":{"siteMetadata":{"title":"CommonLounge Archive"}},"markdownRemark":{"id":"3fbb18ce-c3a4-53c0-a77f-4af1ac22b97b","excerpt":"You might have noticed that you didn’t have to use your password, apart from back when we used the admin interface. You might also have noticed that this means…","html":"<p>You might have noticed that you didn’t have to use your password, apart from back when we used the admin interface. You might also have noticed that this means that anyone can add or edit posts in your blog. We don’t want just anyone to post on our blog! So let’s do something about it.</p>\n<h1><a href=\"#authorizing-addedit-of-posts\"></a>Authorizing add/edit of posts</h1>\n<p>First let’s make things secure. We will protect our <code class=\"language-text\">post_new</code>, <code class=\"language-text\">post_edit</code>, <code class=\"language-text\">post_draft_list</code>, <code class=\"language-text\">post_remove</code> and <code class=\"language-text\">post_publish</code> views so that only logged-in users can access them. Django ships with some nice helpers for doing that, called <em>decorators</em>. Don’t worry about the technicalities now; you can read up on these later. The decorator we want to use is shipped in Django in the module <code class=\"language-text\">django.contrib.auth.decorators</code> and is called <code class=\"language-text\">login_required</code>.</p>\n<p>So edit your <code class=\"language-text\">blog/views.py</code> and add these lines at the top along with the rest of the imports:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">from django.contrib.auth.decorators import login_required</code></pre></div>\n<p>Then add a line before each of the <code class=\"language-text\">post_new</code>, <code class=\"language-text\">post_edit</code>, <code class=\"language-text\">post_draft_list</code>, <code class=\"language-text\">post_remove</code> and <code class=\"language-text\">post_publish</code> views (decorating them) like the following:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@login_required\ndef post_new(request):\n    [...]</code></pre></div>\n<p>That’s it! Now try to access <code class=\"language-text\">http://localhost:8000/post/new/</code>. Notice the difference?</p>\n<blockquote>\n<p>If you just got the empty form, you are probably still logged in from the chapter on the admin-interface. Go to <code class=\"language-text\">http://localhost:8000/admin/logout/</code> to log out, then go to <code class=\"language-text\">http://localhost:8000/post/new</code> again.</p>\n</blockquote>\n<p>You should get one of our beloved errors. This one is quite interesting, actually: the decorator we added will redirect you to the login page, but since that’s not yet available, it raises a “Page not found (404)“.</p>\n<p>Don’t forget to add the decorator from above to <code class=\"language-text\">post_edit</code>, <code class=\"language-text\">post_remove</code>, <code class=\"language-text\">post_draft_list</code> and <code class=\"language-text\">post_publish</code> too.</p>\n<p>Hooray, we’ve reached part of our goal!! Now other people can’t create posts on our blog anymore. Unfortunately we can’t create posts anymore too. So let’s fix that next.</p>\n<h1><a href=\"#log-in-users\"></a>Log in users</h1>\n<p>We could now try to do lots of magical stuff to implement users and passwords and authentication, but doing this correctly is rather complicated. As Django is “batteries included”, someone has done the hard work for us, so we will make further use of the authentication tools provided.</p>\n<hr>\n<h2><a href=\"#log-in-users-django-20\"></a>Log in users: Django 2.0</h2>\n<p>In your <code class=\"language-text\">mysite/urls.py</code> add a url <code class=\"language-text\">path('accounts/login/', views.login, name='login')</code>. You will import these <code class=\"language-text\">views</code> from <code class=\"language-text\">django.contrib.auth</code> so you won’t have to implement them yourselves.</p>\n<p>So the file should now look similar to this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">from django.urls import path, include\nfrom django.contrib import admin\nfrom django.contrib.auth import views\nurlpatterns = [\n    path('admin/', admin.site.urls),\n    path('accounts/login/', views.login, name='login'),\n    path('', include('blog.urls')),\n]</code></pre></div>\n<h2><a href=\"#log-in-users-django-111\"></a>Log in users: Django 1.11</h2>\n<p>In your <code class=\"language-text\">mysite/urls.py</code> add a url <code class=\"language-text\">url(r'^accounts/login/$', views.login, name='login')</code>. You will import these <code class=\"language-text\">views</code> from <code class=\"language-text\">django.contrib.auth</code> so you won’t have to implement them yourselves.</p>\n<p>So the file should now look similar to this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">from django.conf.urls import include, url\nfrom django.contrib import admin\nfrom django.contrib.auth import views\nurlpatterns = [\n    url(r'^admin/', admin.site.urls),\n    url(r'^accounts/login/$', views.login, name='login'),\n    url(r'', include('blog.urls')),\n]</code></pre></div>\n<hr>\n<p>Then we need a template for the login page, so create a directory <code class=\"language-text\">blog/templates/registration</code> and a file inside named <code class=\"language-text\">login.html</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">{% extends \"blog/base.html\" %}\n{% block content %}\n    {% if form.errors %}\n        &lt;p>Your username and password didn't match. Please try again.&lt;/p>\n    {% endif %}\n    &lt;form method=\"post\" action=\"{% url 'login' %}\">\n    {% csrf_token %}\n        &lt;table>\n        &lt;tr>\n            &lt;td>{{ form.username.label_tag }}&lt;/td>\n            &lt;td>{{ form.username }}&lt;/td>\n        &lt;/tr>\n        &lt;tr>\n            &lt;td>{{ form.password.label_tag }}&lt;/td>\n            &lt;td>{{ form.password }}&lt;/td>\n        &lt;/tr>\n        &lt;/table>\n        &lt;input type=\"submit\" value=\"login\" />\n        &lt;input type=\"hidden\" name=\"next\" value=\"{{ next }}\" />\n    &lt;/form>\n{% endblock %}</code></pre></div>\n<p>You will see that this also makes use of our <em>base</em> template for the overall look and feel of your blog.</p>\n<p>The nice thing here is that this <em>just works</em>. We don’t have to deal with handling of the form submission nor with passwords and securing them. Only more thing is left to do. We should add a setting to <code class=\"language-text\">mysite/settings.py</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">LOGIN_REDIRECT_URL = '/'</code></pre></div>\n<p>so that when the login page is accessed directly, it will redirect a successful login to the top-level index (the homepage of our blog).</p>\n<h1><a href=\"#improving-the-layout\"></a>Improving the layout</h1>\n<p>We already set things up so that only authorized users (i.e. us) see the buttons for adding and editing posts. Now we want to make sure a login button appears for everybody else.</p>\n<p>We will add a login button that looks like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">    &lt;a href=\"{% url 'login' %}\" class=\"top-menu\">&lt;span class=\"glyphicon glyphicon-lock\">&lt;/span>&lt;/a></code></pre></div>\n<p>For this we need to edit the templates, so let’s open up <code class=\"language-text\">blog/templates/blog/base.html</code> and change it so the part between the tags looks like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;body>\n    &lt;div class=\"page-header\">\n        {% if user.is_authenticated %}\n            &lt;a href=\"{% url 'post_new' %}\" class=\"top-menu\">&lt;span class=\"glyphicon glyphicon-plus\">&lt;/span>&lt;/a>\n            &lt;a href=\"{% url 'post_draft_list' %}\" class=\"top-menu\">&lt;span class=\"glyphicon glyphicon-edit\">&lt;/span>&lt;/a>\n        {% else %}\n            &lt;a href=\"{% url 'login' %}\" class=\"top-menu\">&lt;span class=\"glyphicon glyphicon-lock\">&lt;/span>&lt;/a>\n        {% endif %}\n        &lt;h1>&lt;a href=\"/\">My Blog&lt;/a>&lt;/h1>\n    &lt;/div>\n    &lt;div class=\"content container\">\n        &lt;div class=\"row\">\n            &lt;div class=\"col-md-8\">\n            {% block content %}\n            {% endblock %}\n            &lt;/div>\n        &lt;/div>\n    &lt;/div>\n&lt;/body></code></pre></div>\n<p>You might recognize the pattern here. There is an if-condition in the template that checks for authenticated users to show the add and edit buttons. Otherwise it shows a login button.</p>\n<h1><a href=\"#more-on-authenticated-users\"></a>More on authenticated users</h1>\n<p>Let’s add some sugar to our templates while we’re at it. First we will add some details to show when we are logged in. Edit <code class=\"language-text\">blog/templates/blog/base.html</code> like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;div class=\"page-header\">\n    {% if user.is_authenticated %}\n        &lt;a href=\"{% url 'post_new' %}\" class=\"top-menu\">&lt;span class=\"glyphicon glyphicon-plus\">&lt;/span>&lt;/a>\n        &lt;a href=\"{% url 'post_draft_list' %}\" class=\"top-menu\">&lt;span class=\"glyphicon glyphicon-edit\">&lt;/span>&lt;/a>\n        &lt;p class=\"top-menu\">Hello {{ user.username }} &lt;small>(&lt;a href=\"{% url 'logout' %}\">Log out&lt;/a>)&lt;/small>&lt;/p>\n    {% else %}\n        &lt;a href=\"{% url 'login' %}\" class=\"top-menu\">&lt;span class=\"glyphicon glyphicon-lock\">&lt;/span>&lt;/a>\n    {% endif %}\n    &lt;h1>&lt;a href=\"/\">My Blog&lt;/a>&lt;/h1>\n&lt;/div></code></pre></div>\n<p>This adds a nice “Hello <em><username></em>” to remind us who we are logged in as, and that we are authenticated. Also, this adds a link to log out of the blog — but as you might notice this isn’t working yet. Let’s fix it!</p>\n<p>We decided to rely on Django to handle login, so let’s see if Django can also handle logout for us. Check <a href=\"https://docs.djangoproject.com/en/2.0/topics/auth/default/\">https://docs.djangoproject.com/en/2.0/topics/auth/default/</a> and see if you find something.</p>\n<blockquote>\n<p>If you’re using Django 1.11, use this link instead <a href=\"https://docs.djangoproject.com/en/1.11/topics/auth/default/\">https://docs.djangoproject.com/en/1.11/topics/auth/default/</a> and see if you find something.</p>\n</blockquote>\n<hr>\n<p>Done reading? By now you may be thinking about adding a URL in <code class=\"language-text\">mysite/urls.py</code> pointing to Django’s logout view (i.e. <code class=\"language-text\">django.contrib.auth.views.logout</code>), like this:</p>\n<hr>\n<h2><a href=\"#django-20\"></a>Django 2.0</h2>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">from django.urls import path, include\nfrom django.contrib import admin\nfrom django.contrib.auth import views\nurlpatterns = [\n    path('admin/', admin.site.urls),\n    path('accounts/login/', views.login, name='login'),\n    path('accounts/logout/', views.logout, name='logout', kwargs={'next_page': '/'}),\n    path('', include('blog.urls')),\n]</code></pre></div>\n<hr>\n<h2><a href=\"#django-111\"></a>Django 1.11</h2>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">from django.conf.urls import include, url\nfrom django.contrib import admin\nfrom django.contrib.auth import views\nurlpatterns = [\n    url(r'^admin/', admin.site.urls),\n    url(r'^accounts/login/$', views.login, name='login'),\n    url(r'^accounts/logout/$', views.logout, name='logout', kwargs={'next_page': '/'}),\n    url(r'', include('blog.urls')),\n]</code></pre></div>\n<p>That’s it! If you followed all of the above up to this point (and did the homework), you now have a blog where you</p>\n<ul>\n<li>need a username and password to log in,</li>\n<li>need to be logged in to add, edit, publish or delete posts,</li>\n<li>and can log out again.</li>\n</ul>","frontmatter":{"title":"Adding Security to your Website via a User Login System","date":"May 17, 2018","description":""}}},"pageContext":{"slug":"/adding-security-to-your-website-via-a-user-login-system-2560f33dbf05440e9944dd21c5f26b82/","previous":{"fields":{"slug":"/code-editor-44de79864b8a4fca9aaf310c7abe5d4c/"},"frontmatter":{"title":"Code Editor"}},"next":{"fields":{"slug":"/hands-on-assignment-creating-an-api-part-1-17722b15451b487aa11d2a4f678684fc/"},"frontmatter":{"title":"Hands-on Assignment: Creating an API Part 1"}}}},"staticQueryHashes":["2841359383","2969095810"]}