Ticket #689: 689_nojavaversion.diff

File 689_nojavaversion.diff, 12.7 KB (added by Marc Fargas, 12 years ago)

New version (aka. The Non Java One)

  • django/contrib/auth/backends.py

    diff --git a/django/contrib/auth/backends.py b/django/contrib/auth/backends.py
    index f79929e..bf6e6c5 100644
    a b  
    11from django.db import connection
    22from django.contrib.auth.models import User
    33
    4 try: 
    5     set 
    6 except NameError: 
     4try:
     5    set
     6except NameError:
    77    from sets import Set as set # Python 2.3 fallback
    8        
     8
    99class ModelBackend:
    1010    """
    1111    Authenticate against django.contrib.auth.models.User
    class ModelBackend: 
    5050            cursor.execute(sql, [user_obj.id])
    5151            user_obj._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
    5252        return user_obj._group_perm_cache
    53    
     53
    5454    def get_all_permissions(self, user_obj):
    5555        if not hasattr(user_obj, '_perm_cache'):
    5656            user_obj._perm_cache = set([u"%s.%s" % (p.content_type.app_label, p.codename) for p in user_obj.user_permissions.select_related()])
    class ModelBackend: 
    6868            return User.objects.get(pk=user_id)
    6969        except User.DoesNotExist:
    7070            return None
     71
     72class RemoteUserAuthBackend:
     73
     74    def authenticate(self, username, password=None):
     75        """
     76        Authenticate user - RemoteUserAuth middleware passes REMOTE_USER
     77        as username.
     78        """
     79        if password is not None:
     80            return None
     81        user = None
     82        if username:
     83            username = self.parse_user(username)
     84            try:
     85                user = User.objects.get(username=username)
     86            except User.DoesNotExist:
     87                user = self.unknown_user(username)
     88                user = self.configure_user(user)
     89        return user
     90
     91    def parse_user(self, username):
     92        """ Parse the provided username.
     93        Override this method if you need to do special things with the
     94        username, like stripping @realm or cleaning something like
     95        cn=x,dc=sas,etc.
     96        """
     97        return username
     98
     99    def get_user(self, user_id):
     100        try:
     101            return User.objects.get(pk=user_id)
     102        except User.DoesNotExist:
     103            return None
     104
     105    def unknown_user(self, username):
     106        # Auto-create user
     107        user = User.objects.create_user(username, '')
     108        user.is_staff = False
     109        user.save()
     110        return user
     111
     112    def configure_user(self, user):
     113        """ Configure a user after login.
     114        i.e: to read group membership from LDAP and so on.
     115        """
     116        return user
     117
  • django/contrib/auth/middleware.py

    diff --git a/django/contrib/auth/middleware.py b/django/contrib/auth/middleware.py
    index 42dc15a..cc8a9d8 100644
    a b class AuthenticationMiddleware(object): 
    1010        assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
    1111        request.__class__.user = LazyUser()
    1212        return None
     13
     14class RemoteUserAuthMiddleware(object):
     15    def process_request(self, request):
     16        from django.contrib.auth import authenticate, login
     17        # AuthenticationMiddleware is required to create request.user
     18        error = """The Django RemoteUserAuth middleware requires authentication middleware to be installed. Edit your MIDDLEWARE_CLASSES
     19setting to insert 'django.contrib.auth.middleware.AuthenticationMiddleware' *before* the RemoteUserMiddleware class."""
     20        assert hasattr(request, 'user'), error
     21        if request.user.is_anonymous():
     22            user = None
     23            try:
     24                user = authenticate(username=request.META['REMOTE_USER'])
     25            except KeyError:
     26                pass # No remote user available
     27            if user is not None:
     28                request.user = user    # set request.user to the authenticated user
     29                login(request, user)   # auto-login the user to Django
     30        return None
  • django/contrib/auth/tests.py

    diff --git a/django/contrib/auth/tests.py b/django/contrib/auth/tests.py
    index 329049c..6d49b7c 100644
    a b  
     1import os
     2import unittest
     3from django.contrib.auth.models import User
     4from django.contrib.auth.backends import RemoteUserAuthBackend
     5from django.test.client import Client
     6from django.conf import settings
     7
     8class HttpAuthTest(unittest.TestCase):
     9    def setUp(self):
     10        self.extra_headers = {'REMOTE_USER': 'iamnotanuser'}
     11        self.curr_middleware = settings.MIDDLEWARE_CLASSES
     12        self.curr_auth = settings.AUTHENTICATION_BACKENDS
     13
     14        settings.MIDDLEWARE_CLASSES +=\
     15            ('django.contrib.auth.middleware.RemoteUserAuthMiddleware', )
     16        settings.AUTHENTICATION_BACKENDS =\
     17            ('django.contrib.auth.backends.RemoteUserAuthBackend',)
     18
     19    def testRemoteUserIsRespected(self):
     20        c = Client()
     21        extra_headers = {'REMOTE_USER': 'iamnotanuser'}
     22        res = c.get('/', {}, **self.extra_headers)
     23
     24        u = User.objects.get(username='iamnotanuser')
     25        # wow, the user was created! this works.
     26
     27    def tearDown(self):
     28        # Restore settings to avoid breaking other tests.
     29        settings.MIDDLEWARE_CLASSES = self.curr_middleware
     30        settings.AUTHENTICATION_BACKENDS = self.curr_auth
     31       
    132"""
    233>>> from models import User, AnonymousUser
    334>>> u = User.objects.create_user('testuser', 'test@example.com', 'testpw')
    False 
    2354[]
    2455>>> a.user_permissions.all()
    2556[]
    26 """
    27  No newline at end of file
     57"""
  • new file docs/auth_remote_user.txt

    diff --git a/docs/auth_remote_user.txt b/docs/auth_remote_user.txt
    new file mode 100644
    index 0000000..c3324ad
    - +  
     1======================================================
     2Authenticating against REMOTE_USER from the Web Server
     3======================================================
     4
     5Typically on intranet sites users are already authenticated (i.e. in a Windows
     6domain) by the web server (i.e. using IIS Integrated Authentication).
     7
     8When the web server takes care of authentication it sets the ``REMOTE_USER`` HTTP
     9header for use in the underlying application (i.e. Django). Then it's up to
     10this application take care of the authorization.
     11
     12Django brings all you need to make use of the ``REMOTE_USER`` header bringing you
     13one step furder to single sign-on on enterprise infrastucure!
     14
     15We assume that you have already configured your web server to authenticate
     16users, maybe with mod_auth_sspi in Apache, Integrated Authentication in IIS
     17and so on.
     18
     19Configuring Django
     20==================
     21
     22First of all, you must add the ``RemoteUserAuthMiddleware`` just **after**
     23(never before) ``AuthenticationMiddleware``.
     24
     25After this, you'll have to create you authentication backend that will take
     26care of checking that ``REMOTE_USER`` is valid. But don't be scared,
     27``RemoteUserAuthBackend`` is here to help you.
     28
     29``RemoteUserAuthBackend`` provides a "template" of what you need, you could
     30create a backend that simply inherits it and you are done. It will simply
     31assume that ``REMOTE_USER`` is always correct and create ``User``objects for
     32it.
     33
     34If you want more control, in you inherited authentication backend you can
     35override a few methods:
     36
     37   * ``parse_user``: Should cleanup ``REMOTE_USER`` (i.e. strip @realm from
     38     it). It takes the ``username`` as argument, and must return the cleaned
     39     ``username``.
     40   * ``unkown_user``: Should create and return a ``User`` object, will be
     41     called when a ``User`` object does not exist for ``REMOTE_USER``. Takes
     42     ``username`` as it's only argument.
     43   * ``configure_user``: Will be called after ``unkown_user`` so you can
     44     configure the recently created ``User`` object (in case you did not want
     45     to override ``unkown_user``. Takes the ``User`` instance as an argument.
     46     Should also return the ``User`` instance that represents the User.
     47
     48
     49Examples:
     50
     51    settings.py::
     52
     53        MIDDLEWARE_CLASSES = (
     54            'django.contrib.auth.middleware.AuthenticationMiddleware',
     55            'django.contrib.auth.middleware.RemoteUserAuthMiddleware',
     56            ...
     57            )
     58           
     59        AUTHENTICATION_BACKENDS = (
     60            'django.contrib.auth.backends.RemoteUserAuthBackend',
     61        )
  • docs/authentication.txt

    diff --git a/docs/authentication.txt b/docs/authentication.txt
    index 8f305ba..4794519 100644
    a b This example shows how you might use both ``authenticate()`` and ``login()``:: 
    380380            # Return an 'invalid login' error message.
    381381
    382382.. admonition:: Calling ``authenticate()`` first
    383    
     383
    384384    When you're manually logging a user in, you *must* call
    385385    ``authenticate()`` before you call ``login()``. ``authenticate()``
    386386    sets an attribute on the ``User`` noting which authentication
    387387    backend successfully authenticated that user (see the `backends
    388388    documentation`_ for details), and this information is needed later
    389389    during the login process.
    390    
     390
    391391.. _backends documentation: #other-authentication-sources
    392392
    393393Manually checking a user's password
    introduced in Python 2.4:: 
    460460
    461461In the Django development version, ``login_required`` also takes an optional
    462462``redirect_field_name`` parameter. Example::
    463    
     463
    464464    from django.contrib.auth.decorators import login_required
    465465
    466466    def my_view(request):
    In the Django development version, ``login_required`` also takes an optional 
    468468    my_view = login_required(redirect_field_name='redirect_to')(my_view)
    469469
    470470Again, an equivalent example of the more compact decorator syntax introduced in Python 2.4::
    471    
     471
    472472    from django.contrib.auth.decorators import login_required
    473473
    474474    @login_required(redirect_field_name='redirect_to')
    Again, an equivalent example of the more compact decorator syntax introduced in 
    479479
    480480    * If the user isn't logged in, redirect to ``settings.LOGIN_URL``
    481481      (``/accounts/login/`` by default), passing the current absolute URL
    482       in the query string as ``next`` or the value of ``redirect_field_name``. 
     482      in the query string as ``next`` or the value of ``redirect_field_name``.
    483483      For example:
    484484      ``/accounts/login/?next=/polls/3/``.
    485485    * If the user is logged in, execute the view normally. The view code is
    plug in another authentication sources. You can override Django's default 
    10191019database-based scheme, or you can use the default system in tandem with other
    10201020systems.
    10211021
     1022.. admonition:: Handling authentication at the web server
     1023
     1024    There's a very specific situation/scenario in which you want to handle
     1025    authentication at the web server's level (i.e. standard HTTP AUTH) and want
     1026    Django to honour this authentication. This is covered in a separate page:
     1027    `Authenticating against REMOTE_USER from the Web Server`_
     1028
     1029.. _Authenticating against REMOTE_USER from the Web Server: ../auth_remote_user/
     1030
    10221031Specifying authentication backends
    10231032----------------------------------
    10241033
    object the first time a user authenticates:: 
    11191128Handling authorization in custom backends
    11201129-----------------------------------------
    11211130
    1122 Custom auth backends can provide their own permissions. 
     1131Custom auth backends can provide their own permissions.
    11231132
    11241133The user model will delegate permission lookup functions
    11251134(``get_group_permissions()``, ``get_all_permissions()``, ``has_perm()``, and
    one backend grants. 
    11321141
    11331142The simple backend above could implement permissions for the magic admin fairly
    11341143simply::
    1135        
     1144
    11361145    class SettingsBackend:
    1137    
     1146
    11381147        # ...
    11391148
    11401149        def has_perm(self, user_obj, perm):
    simply:: 
    11421151                return True
    11431152            else:
    11441153                return False
    1145                
     1154
    11461155This gives full permissions to the user granted access in the above example. Notice
    11471156that the backend auth functions all take the user object as an argument, and
    11481157they also accept the same arguments given to the associated ``User`` functions.
  • docs/request_response.txt

    diff --git a/docs/request_response.txt b/docs/request_response.txt
    index 2445b3e..81ef686 100644
    a b All attributes except ``session`` should be considered read-only. 
    109109        * ``QUERY_STRING`` -- The query string, as a single (unparsed) string.
    110110        * ``REMOTE_ADDR`` -- The IP address of the client.
    111111        * ``REMOTE_HOST`` -- The hostname of the client.
     112        * ``REMOTE_USER`` -- The user authenticated by the web server, if any.
    112113        * ``REQUEST_METHOD`` -- A string such as ``"GET"`` or ``"POST"``.
    113114        * ``SERVER_NAME`` -- The hostname of the server.
    114115        * ``SERVER_PORT`` -- The port of the server.
Back to Top