After that was done, I wrote a Django authentication backend based on [5].
What I did:
- Add a link to my customized registration/login.html page which points to a special location which is protected by mod_ntlm, e.g.:
<a href="./remote_user/?next={{next}}">Intranet authentication</a>
- Configure this location in Apache2 for mod_ntlm:
Here, I suppose that all django mod_python config is already included in /.
#NTLM Auth
AuthName NTAuth
AuthType NTLM
NTLMAuth on
NTLMAuthoritative on
NTLMDomain DOMAIN
NTLMServer pdc.sercer
NTLMBasicAuth off
# NTLMBasicRealm SISAM
NTLMLockfile /tmp/_my.lck
# NTLMBackup
Require valid-user
# Satisfy all
- Write the authentication backend and a view that captures the "REMOTE_USER" environment variable, authenticates and logs in the user. Here is my "remoteuser.py":
"""User auth based on REMOTE_USER.
To make it work you need:
- add RemoteUserAuthBackend en settings.py, en AUTHENTICATION_BACKENDS
- add ('/login/remote_user/', 'sisamapp.auth.remoteuser.remote_user_login') to your urls.py
- enable the apache module (e.g. mod_ntlm)
- configure Apache /login/remote_user/, e.g. for mod_ntlm:
#NTLM Auth
AuthName NTAuth
AuthType NTLM
NTLMAuth on
NTLMAuthoritative on
NTLMDomain DOMAIN
NTLMServer MACHINE or IP
# NTLMBasicAuth off
# NTLMBasicRealm SISAM
NTLMLockfile /tmp/_my.lck
# NTLMBackup
Require valid-user
# Satisfy all
We suppose here that the / location has already all django stuff configured (i.e. PythonHandler)
"""
from django.contrib.auth.models import User
import sys
log = sys.stderr.write
# copied from http://code.djangoproject.com/attachment/ticket/689/remote_user_2.diff
from django.contrib.auth.backends import ModelBackend
class RemoteUserAuthBackend(ModelBackend):
def authenticate(self, **credentials):
"""
Authenticate user - RemoteUserAuth middleware passes REMOTE_USER
as username. password param is not used, just added in case :)
"""
try:
type = credentials['type']
if type == "remote_user":
username = credentials['username']
except:
username = None
if not username:
return None
user = None
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise User.DoesNotExist, _T('User %s not configured in this application.') % username
return user
class NoRemoteUserInfoAvailable(Exception):
pass
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
import re
from django.utils.translation import ugettext as _T
def render_notice(request, errornote, msg):
return render_to_response('registration/notice.html',
{'errornote': errornote, 'msg': msg },
context_instance = RequestContext(request))
def remote_user_login(request):
error = """
remote_user_login requires Django authentication middleware to be installed. (Include in MIDDLEWARE_CLASSES setting 'django.contrib.auth.middleware.AuthenticationMiddleware'.
"""
msg = _T('Use the __standard login form__ to provide alternative credentials.')
msg = re.sub('__(.*)__',r'<a href="../?next=%s">\1</a>' % request.GET.get('next',''), msg, re.UNICODE)
try:
username = request.META['REMOTE_USER']
log("Got REMOTE_USER=%s\n" % username)
except:
return render_notice(request,
errornote=_T('Server does not provide REMOTE_USER.'),
msg=msg)
if not username:
return render_notice(request,
errornote=_T('Could not get your credentials. Are you accessing from anywhere outside the domain or a browser that does not support intranet authentication?'),
msg=msg)
from django.contrib.auth import authenticate, login
# AuthenticationMiddleware is required to create request.user
assert hasattr(request, 'user'), self.error
if request.user.is_anonymous():
log("Request is anonymous. Trying to authenticate user %s\n" % username)
try:
user = authenticate(username=username, type="remote_user")
except:
user = None
log("User is %s\n" % user)
if user is not None:
request.user = user # set request.user to the authenticated user
login(request, user) # auto-login the user to Django
return HttpResponseRedirect(request.GET.get('next','/'))
return render_notice(request,
errornote=_T('Your username (%s) is not registered here.') % username,
msg=msg)
# user is already authenticated, should logout first
msg = _T('You have to logout first using __this link__ before logging in again.')
msg = re.sub('__(.*)__',r'<a href="../../logout/">\1</a>', msg, re.UNICODE)
return render_notice(request,
errornote=_T('You are already authenticated.'),
msg=msg)
Some notes here:- remote_user 'authenticate' uses explicitly another signature as ModelBackend 'authenticate', i.e. it needs the 'type' argument. If you used the same signature (username, password) there is a possibility that a user authenticates without any password!
- In my configuration, when I acces with Firefox/Linux /login/remote_user/, a browser authentication dialog pops up. I was not able to get rid of it.
Links: - remote_user 'authenticate' uses explicitly another signature as ModelBackend 'authenticate', i.e. it needs the 'type' argument. If you used the same signature (username, password) there is a possibility that a user authenticates without any password!
- http://modntlm.sourceforge.net/
- http://erny-rev.blogspot.com/2007/11/compiling-modntlm-for-apache2-in-ubuntu.html
- http://geeklab.wikidot.com/samba-pdc
- http://us1.samba.org/samba/docs/man/Samba-HOWTO-Collection/domain-member.html#machine-trust-accounts
- http://code.djangoproject.com/attachment/ticket/689/remote_user_2.diff
No hay comentarios:
Los comentarios nuevos no están permitidos.