Authorization in django webapp
In this blog I am trying to explain how django-project implements a common web application feature ‘authorization’. django packages authentication(i.e Identifying user uniquely by passwords) and authorization (i.e Allowing/denying user to access particular feature/url/action)into an inbulit app called ‘auth’.
When you think about authorization in webapp, it seems like really complex and worrisome. django-project comes along with well thought features and reusable pieces of codes. django takes the full advantage of OOPS concepts, by inheriting mixin in classes or decorating your functions, one can implement apparently super complex features like authorization almost with out having to writing a new line of code.
User Story:
Lets take an example of simple and most common case. We have two group of users, say “foo”and “bar”. When they login they need to be routed to say, url /dashboard_foo/
and /dashboard_bar/
respectively.
Permissions:
django-project built-in auth app, which contains three django model objects User
,Group
and Permission
. User
andGroup
have many2many connection with each other (that means many users can belong to one group and one user can belong to many groups). And also both User
and Group
have many2many connection with Permission
.
By default django creates three Permission
objects for each model objects. That means , say you have model object Poll
, then there would be permission objects add_poll
, change_poll
and delete_poll
.
Try this
Permission.objects.get(codename=add_<model_obejct_lowercase>)
Permission.objects.get(codename=add_poll)
Assigning permissions:
Using admin interface of django one can easily manage group, users and assign them permissions.
Actual gate keeping:
django being django, solves this whole authorization in pretty elegant way. In django every url pattern match is mapped with an callable (class/function).
Lets say url /foo_dashboard/
is rendered by function based view foo
or by a class based view Foo
. django authorizes these callable views by checking if request.user
is authenticated and have specific permission before calling them. If the user is not authenticated or authorized it redirects to LOGIN_URL
defined in settings.py
How do you do it?
For function based view ,use permission_required
decorator. It takes in str
argument 'appname.<permission_codename>'
from django.contrib.auth.decorators import permission_required@permission_required('appname.<permission_codename>')
def foo(request):
pass# Example:
@permission_required('poll.add_poll')
def foo(request):
pass
For Class Based views
from django.contrib.auth.mixins import PermissionRequiredMixinclass Foo(PermissionRequiredMixin, View):
permission_required = 'appname.<permission_codename>'
pass#Example:class Foo(PermissionRequiredMixin, View):
permission_required = 'poll.add_poll'
pass
More and More:
There are other mixin and decorator like LoginRequiredMixin
and login_required
respectively which can be used to authorize common urls like reset passwords. Here is the source code
django thus proves the rapid development by using reusable codes like mixins, decorator and abstract classes, that do magic in few lines of codes. If you find this interesting visit, APIMonk an django based project to automate API development, testing and deployment.