Ticket #10809: modwsgi_auth_handler.4.diff

File modwsgi_auth_handler.4.diff, 9.1 KB (added by David Fischer, 10 years ago)

Updated docs and added tests

  • docs/howto/apache-auth.txt

     
    22Authenticating against Django's user database from Apache
    33=========================================================
    44
    5 .. warning::
    6 
    7     Support for mod_python has been deprecated within Django. At that
    8     time, this method of authentication will no longer be provided by
    9     Django. The community is welcome to offer its own alternate
    10     solutions using WSGI middleware or other approaches.
    11 
    125Since keeping multiple authentication databases in sync is a common problem when
    136dealing with Apache, you can configuring Apache to authenticate against Django's
    147:doc:`authentication system </topics/auth>` directly. For example, you
     
    2417.. _Subversion: http://subversion.tigris.org/
    2518.. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
    2619
    27 Configuring Apache
    28 ==================
     20Authentication with mod_wsgi
     21============================
    2922
    30 To check against Django's authorization database from a Apache configuration
    31 file, you'll need to use mod_python's ``PythonAuthenHandler`` directive along
     23Make sure that mod_wsgi is installed and activated and that you have
     24followed the steps to setup
     25:doc:`Apache with mod_wsgi <deployment/wsgi/modwsgi>`
     26
     27Next, edit your Apache configuration to add a path that you want
     28only authenticated users to be able to view:
     29
     30.. code-block:: apache
     31
     32    WSGIScriptAlias / /path/to/mysite/config/mysite.wsgi
     33   
     34    WSGIProcessGroup %{GLOBAL}
     35    WSGIApplicationGroup django
     36   
     37    <Location "/secret">
     38        AuthType Basic
     39        AuthName "Top Secret"
     40        Require valid-user
     41        AuthBasicProvider wsgi
     42        WSGIAuthUserScript /path/to/mysite/config/mysite.wsgi
     43    </Location>
     44
     45The ``WSGIAuthUserScript`` directive tells mod_wsgi to execute the
     46``check_password`` function in that script passing the user name and
     47password that it receives from the prompt. In this example,
     48the ``WSGIAuthUserScript`` is the same as the ``WSGIScriptAlias`` that
     49defines your application.
     50
     51.. admonition:: Using Apache 2.2 with authentication
     52
     53    Make sure that ``mod_auth_basic`` and ``mod_authz_user`` are loaded.
     54
     55    These might be compiled statically into Apache, or you might need to use
     56    LoadModule to load them dynamically in your ``httpd.conf``:
     57
     58    .. code-block:: apache
     59       
     60        LoadModule auth_basic_module modules/mod_auth_basic.so
     61        LoadModule authz_user_module modules/mod_authz_user.so
     62
     63Finally, edit your WSGI auth script ``mysite.wsgi`` to tie Apache's 
     64authentication to yoursite's users:
     65
     66.. code-block:: python
     67   
     68    import os
     69    import sys
     70   
     71    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'
     72
     73    from django.contrib.auth.handlers.modwsgi import check_user
     74   
     75    from django.core.handlers.wsgi import WSGIHandler
     76    application = WSGIHandler()
     77
     78
     79Requests beginning with ``/secret/`` will now require a user to authenticate.
     80
     81The mod_wsgi `access control mechanisms documentation`_ provides additional
     82details and information about alternative methods of authentication.
     83
     84.. _access control mechanisms documentation: http://code.google.com/p/modwsgi/wiki/AccessControlMechanisms
     85
     86Authorization with mod_wsgi and Django groups
     87---------------------------------------------
     88
     89In addition, mod_wsgi also provides functionality to restrict a particular
     90location to members of a group.
     91
     92In this case, the Apache configuration should look like this:
     93
     94.. code-block:: apache
     95
     96    WSGIScriptAlias / /path/to/mysite/config/mysite.wsgi
     97   
     98    WSGIProcessGroup %{GLOBAL}
     99    WSGIApplicationGroup django
     100   
     101    <Location "/secret">
     102        AuthType Basic
     103        AuthName "Top Secret"
     104        AuthBasicProvider wsgi
     105        WSGIAuthUserScript /path/to/mysite/config/mysite.wsgi
     106        WSGIAuthGroupScript /path/to/mysite/config/mysite.wsgi
     107        Require group secret-agents
     108        Require valid-user
     109    </Location>
     110   
     111Because of the ``WSGIAuthGroupScript`` directive, the same WSGI auth script
     112``mysite.wsgi`` must also import the method ``groups_for_user`` which
     113returns a list of the user's groups.
     114
     115.. code-block:: python
     116   
     117    from django.contrib.auth.handlers.modwsgi import check_user, groups_for_user
     118   
     119Requests for ``/secret/`` will now also require a user to a member of the
     120"secret-agents" group.
     121
     122Authentication with mod_python
     123==============================
     124
     125.. warning::
     126
     127    Support for mod_python has been deprecated within Django. At that
     128    time, this method of authentication will no longer be provided by
     129    Django. The community is welcome to offer its own alternate
     130    solutions using WSGI middleware or other approaches.
     131
     132To check against Django's authorization database from mod_python,
     133you'll need to use mod_python's ``PythonAuthenHandler`` directive along
    32134with the standard ``Auth*`` and ``Require`` directives:
    33135
    34136.. code-block:: apache
     
    89191            PythonAuthenHandler django.contrib.auth.handlers.modpython
    90192        </Location>
    91193
    92 By default, the authentication handler will limit access to the ``/example/``
    93 location to users marked as staff members.  You can use a set of
     194By default, the mod_python authentication handler will limit access to the
     195``/example/`` location to users marked as staff members.  You can use a set of
    94196``PythonOption`` directives to modify this behavior:
    95197
    96198================================  =========================================
  • django/contrib/auth/handlers/modwsgi.py

     
     1from django.contrib.auth.models import User
     2from django import db
     3
     4def check_password(environ, username, password):
     5    """
     6    Authenticates against Django's auth database
     7    """
     8
     9    db.reset_queries()
     10
     11    try:
     12        # verify the user exists
     13        try:
     14            user = User.objects.get(username=username, is_active=True)
     15        except User.DoesNotExist:
     16            return None
     17
     18        # verify the password for the given user
     19        if user.check_password(password):
     20            return True
     21        else:
     22            return False
     23    finally:
     24        db.close_connection()
     25
     26def groups_for_user(environ, username):
     27    """
     28    Authorizes a user based on groups
     29    """
     30
     31    db.reset_queries()
     32
     33    try:
     34        try: 
     35            user = User.objects.get(username=username, is_active=True)
     36        except User.DoesNotExist: 
     37            return []
     38
     39        return [group.name.encode('utf-8') for group in user.groups.all()]
     40    finally:
     41        db.close_connection()
  • django/contrib/auth/tests/__init__.py

     
    1717from django.contrib.auth.tests.views import (AuthViewNamedURLTests,
    1818    PasswordResetTest, ChangePasswordTest, LoginTest, LogoutTest,
    1919    LoginURLSettings)
     20from django.contrib.auth.tests.handlers import ModWsgiHandlerTestCase
    2021
    2122# The password for the fixture data users is 'password'
  • django/contrib/auth/tests/handlers.py

     
     1from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user
     2from django.contrib.auth.models import User, Group
     3from django.test import TestCase
     4
     5class ModWsgiHandlerTestCase(TestCase):
     6    """
     7    Tests for the mod_wsgi authentication handler
     8    """
     9
     10    def setUp(self):
     11        user1 = User.objects.create_user('test', 'test@example.com', 'test')
     12        user2 = User.objects.create_user('test1', 'test1@example.com', 'test1')
     13
     14        group = Group.objects.create(name='test_group')
     15        user1.groups.add(group)
     16       
     17
     18    def testCheckPassword(self):
     19        """
     20        Verify that check_password returns the correct values as per
     21        http://code.google.com/p/modwsgi/wiki/AccessControlMechanisms#Apache_Authentication_Provider
     22        """
     23
     24        # User not in database
     25        self.assertTrue(check_password({}, 'unknown', '') is None)
     26
     27        # Valid user with correct password
     28        self.assertTrue(check_password({}, 'test', 'test'))
     29
     30        # Valid user with incorrect password
     31        self.assertFalse(check_password({}, 'test', 'incorrect'))
     32
     33    def testGroupsForUser(self):
     34        """
     35        Check that groups_for_user returns correct values as per
     36        http://code.google.com/p/modwsgi/wiki/AccessControlMechanisms#Apache_Group_Authorisation
     37        """
     38
     39        # User not in database
     40        self.assertEqual(groups_for_user({}, 'unknown'), [])
     41
     42        self.assertEqual(groups_for_user({}, 'test'), ['test_group'])
     43        self.assertEqual(groups_for_user({}, 'test2'), [])
Back to Top