Django

Code

Ticket #689: 689-r9733.diff

File 689-r9733.diff, 10.1 kB (added by telenieko, 1 year ago)

Updated patch

  • a/django/contrib/auth/backends.py

    old new  
    7878            return User.objects.get(pk=user_id) 
    7979        except User.DoesNotExist: 
    8080            return None 
     81 
     82class RemoteUserAuthBackend: 
     83 
     84    def authenticate(self, username, password=None): 
     85        """ 
     86        Authenticate user - RemoteUserAuth middleware passes REMOTE_USER 
     87        as username. 
     88        """ 
     89        if password is not None: 
     90            return None 
     91        user = None 
     92        if username: 
     93            username = self.parse_user(username) 
     94            try: 
     95                user = User.objects.get(username=username) 
     96            except User.DoesNotExist: 
     97                user = self.unknown_user(username) 
     98                user = self.configure_user(user) 
     99        return user 
     100 
     101    def parse_user(self, username): 
     102        """ Parse the provided username. 
     103        Override this method if you need to do special things with the 
     104        username, like stripping @realm or cleaning something like 
     105        cn=x,dc=sas,etc. 
     106        """ 
     107        return username 
     108 
     109    def get_user(self, user_id): 
     110        try: 
     111            return User.objects.get(pk=user_id) 
     112        except User.DoesNotExist: 
     113            return None 
     114 
     115    def unknown_user(self, username): 
     116        """Auto-create user. Called only if User object doesn't already exist 
     117        for username. 
     118        """ 
     119        user = User.objects.create_user(username, '') 
     120        user.is_staff = False 
     121        user.save() 
     122        return user 
     123 
     124    def configure_user(self, user): 
     125        """ Configure a user after login. 
     126        i.e: to read group membership from LDAP and so on. 
     127        Called only if user User object has just been created." 
     128        """ 
     129        return user 
  • a/django/contrib/auth/middleware.py

    old new  
    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 
     31 
  • a/django/contrib/auth/tests/__init__.py

    old new  
    1 from django.contrib.auth.tests.basic import BASIC_TESTS 
     1from django.contrib.auth.tests.basic import BASIC_TESTS, HttpAuthTest 
    22from django.contrib.auth.tests.views import PasswordResetTest, ChangePasswordTest 
    33from django.contrib.auth.tests.forms import FORM_TESTS 
    44from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS 
     
    1111    'FORM_TESTS': FORM_TESTS, 
    1212    'TOKEN_GENERATOR_TESTS': TOKEN_GENERATOR_TESTS, 
    1313    'CHANGEPASSWORD_TESTS': ChangePasswordTest, 
     14    'HTTPAUTH_TESTS': HttpAuthTest, 
    1415} 
  • a/django/contrib/auth/tests/basic.py

    old new  
    5454>>> u.password 
    5555u'!' 
    5656""" 
     57 
     58from django.test import TestCase 
     59from django.contrib.auth.models import User 
     60from django.conf import settings 
     61 
     62class HttpAuthTest(TestCase): 
     63    def setUp(self): 
     64        self.curr_middleware = settings.MIDDLEWARE_CLASSES 
     65        self.curr_auth = settings.AUTHENTICATION_BACKENDS 
     66 
     67        settings.MIDDLEWARE_CLASSES +=\ 
     68            ('django.contrib.auth.middleware.RemoteUserAuthMiddleware', ) 
     69        settings.AUTHENTICATION_BACKENDS =\ 
     70            ('django.contrib.auth.backends.RemoteUserAuthBackend',) 
     71 
     72    def test_remote_user(self): 
     73        "REMOTE_USER variable set by Web server is respected" 
     74        extra_headers = {'REMOTE_USER': 'iamnotanuser'} 
     75        response = self.client.get('/', **extra_headers) 
     76 
     77        u = User.objects.get(username='iamnotanuser') 
     78        # if no exception ws raises above it means this works. 
     79 
     80    def tearDown(self): 
     81        # Restore settings to avoid breaking other tests. 
     82        settings.MIDDLEWARE_CLASSES = self.curr_middleware 
     83        settings.AUTHENTICATION_BACKENDS = self.curr_auth 
  • /dev/null

    old new  
     1.. _topics-auth-remote-user: 
     2 
     3====================================================== 
     4Authenticating against REMOTE_USER from the Web Server 
     5====================================================== 
     6 
     7Typically on intranet sites users are already authenticated by the web server 
     8(e.g. a Windows domain using IIS Integrated Authentication, or an environment 
     9using solutions like Apache `mod_authnz_ldap`_, `CAS`_, `Cosign`_, `WebAuth`_, 
     10etc.) 
     11 
     12.. _mod_authnz_ldap: http://httpd.apache.org/docs/2.2/mod/mod_authnz_ldap.html 
     13.. _CAS: http://www.ja-sig.org/products/cas/ 
     14.. _Cosign: http://weblogin.org 
     15.. _WebAuth: http://www.stanford.edu/services/webauth/ 
     16 
     17When the web server takes care of authentication it sets the ``REMOTE_USER`` 
     18header for use in the underlying application. Then it's up to this 
     19application to take care of the authorization. 
     20 
     21Django can be configured to make use of the ``REMOTE_USER`` header making it 
     22possible to integrate your Django applications with a pre-existing single 
     23sign-on enterprise infrastructure. 
     24 
     25We assume that you have already configured your web server to authenticate 
     26users (i.e. by using ``mod_auth_sspi`` in Apache, Integrated Authentication in 
     27IIS or one of the solutions listed above). 
     28 
     29Configuring Django 
     30================== 
     31 
     32First of all, you must add the ``RemoteUserAuthMiddleware`` to the 
     33``MIDDLEWARE_CLASSES`` setting just **after** (never before) 
     34``AuthenticationMiddleware``. 
     35 
     36With this setup, ``RemoteUserAuthMiddleware`` will detect the ``REMOTE_USER`` 
     37variable in the requests and will auto-login the user by using the username 
     38contained in such variable. The user must already exist in the authentication 
     39backend being used by Django. 
     40 
     41Additionally, if you want the non-existent users to be automatically added 
     42to the store of the authentication backend being used by Django , include the 
     43``RemoteUserAuthBackend`` in the ``AUTHENTICATION_BACKENDS`` setting. 
     44 
     45If you want even more control, you can create your own authentication backend 
     46that inherits from ``RemoteUserAuthBackend``, override a few methods: 
     47 
     48   * ``parse_user``: Should cleanup ``REMOTE_USER`` (i.e. strip @realm from 
     49     it). It takes the ``username`` as argument, and must return the cleaned 
     50     ``username``. 
     51   * ``unkown_user``: Will be called when no ``User`` object exist for 
     52     ``REMOTE_USER``. Takes ``username`` as it's only argument. Should create 
     53     and return an ``User`` object. 
     54   * ``configure_user``: Will be called after ``unknown_user`` only when a new 
     55     ``User`` object has been created so you can configure it. Takes the 
     56     newly created ``User`` instance as it's only argument. Should also return 
     57     the ``User`` instance that represents the user. 
     58 
     59and use it in the ``AUTHENTICATION_BACKENDS`` setting. 
     60 
     61Examples: 
     62 
     63    settings.py:: 
     64 
     65        MIDDLEWARE_CLASSES = ( 
     66            'django.contrib.auth.middleware.AuthenticationMiddleware', 
     67            'django.contrib.auth.middleware.RemoteUserAuthMiddleware', 
     68            ... 
     69            ) 
     70 
     71        AUTHENTICATION_BACKENDS = ( 
     72            'django.contrib.auth.backends.RemoteUserAuthBackend', 
     73        ) 
  • a/docs/topics/auth.txt

    old new  
    12241224database-based scheme, or you can use the default system in tandem with other 
    12251225systems. 
    12261226 
     1227.. versionadded:: 1.1 
     1228    Handling authentication at the web server was added in Django 1.1 
     1229 
     1230Handling authentication at the web server 
     1231----------------------------------------- 
     1232 
     1233There's a very specific situation/scenario in which you want to handle 
     1234authentication at the web server's level (i.e. standard HTTP AUTH) and want 
     1235Django to honour this authentication. This is covered in 
     1236:ref:`Authenticating against REMOTE_USER<topics-auth-remote-user>` 
     1237 
    12271238Specifying authentication backends 
    12281239---------------------------------- 
    12291240 
     
    13601371the ``auth_permission`` table most of the time. 
    13611372 
    13621373.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py 
     1374 
  • a/docs/topics/index.txt

    old new  
    1717   files 
    1818   testing 
    1919   auth 
     20   auth-remote-user 
    2021   cache 
    2122   email 
    2223   i18n