Django 中的 Ntlm/Kerberos 身份验证

发布于 2024-09-12 17:08:56 字数 644 浏览 3 评论 0原文

我正在寻找有关将 Windows 身份验证支持添加到 django 应用程序中的指南,特别是 OSQA

我知道 http://code.google.com/p/python-ntlm/ 还看到了这篇文章: http://erny-rev .blogspot.com/2007/11/ntlm-authentication-in-django.html 但我不是Django开发者,我只想在Windows环境中部署OSQA(内网,所以我需要添加Windows身份验证)。所以我正在寻找简单的分步描述。

(我已经设法使用 SQL Server 在 Windows 上部署 OSQA 站点,并且它正在工作)

更新:
我不仅希望获得针对 AD 的身份验证,还希望在 IE 中获得类似 SSO 的行为。当用户在 IE 中访问我的基于 django 的站点时,它会自动使用其域帐户进行身份验证。

I'm looking for a guide about adding windows authentication support into a django app, particulary OSQA

I'm aware about http://code.google.com/p/python-ntlm/
And also saw this post: http://erny-rev.blogspot.com/2007/11/ntlm-authentication-in-django.html
But I'm not a Django-dev, I just want to deploy OSQA in Windows enviroment (intranet, so I need to add windows authentication). So I'm looking for simple step-by-step description.

(I've managed to deploy a OSQA site on windows with SQL Server and it's working)

UPDATE:
I'd like to get not just auth against AD but SSO-like behavior in IE. As a user access my django-based site in IE it'd automaticaly authenticated with its domain account.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟火散人牵绊 2024-09-19 17:08:56

您可以使用 Apache、mod_auth_kerb 和 REMOTE_USER 身份验证以及托管为 mod_wsgi 的 Django 来完成此操作。

这是我们使用的一些配置的示例:

WSGIDaemonProcess myapp user=myapp group=myapp processes=5 threads=1
WSGIProcessGroup myapp
WSGIScriptAlias /myapp /home/wolapp/code/wolapp.wsgi
<VirtualHost ...>
    <Location /myapp>
            AuthType                Kerberos
            AuthName                "Domain Login"
            KrbMethodNegotiate      On
            KrbMethodK5Passwd       On
            KrbAuthRealms           YOUR.DOMAIN
            Krb5Keytab              /etc/krb5.keytab
            KrbServiceName          HTTP/server.your.domain
            require                 valid-user
    </Location>
</VirtualHost>

然后您需要进行设置:

http://docs.djangoproject.com/en/dev/howto/auth-remote-user/

需要注意的几个警告:

  1. Opera 在我们的测试中完全失败;它无法处理“Negotiate”标头
  2. 如果计算机位于域中,则 IE 可以正常工作,但如果不在域中,则会两次提示您输入密码 - 第一次计算机使用“ITSNAME\username”时会失败;第二次裸“用户名”

希望这有帮助。

You can do this using Apache, mod_auth_kerb and REMOTE_USER authentication with Django hosted as mod_wsgi.

Here is an example of some config we use:

WSGIDaemonProcess myapp user=myapp group=myapp processes=5 threads=1
WSGIProcessGroup myapp
WSGIScriptAlias /myapp /home/wolapp/code/wolapp.wsgi
<VirtualHost ...>
    <Location /myapp>
            AuthType                Kerberos
            AuthName                "Domain Login"
            KrbMethodNegotiate      On
            KrbMethodK5Passwd       On
            KrbAuthRealms           YOUR.DOMAIN
            Krb5Keytab              /etc/krb5.keytab
            KrbServiceName          HTTP/server.your.domain
            require                 valid-user
    </Location>
</VirtualHost>

You then need to setup this:

http://docs.djangoproject.com/en/dev/howto/auth-remote-user/

A couple of caveats to note:

  1. Opera fails completely in our testing; it can't handle the "Negotiate" header
  2. IE works fine if the machine is in the domain, but if it isn't, you get prompted for your password twice - the first time the machine uses "ITSNAME\username" which fails; the second time the bare "username"

Hope this helps.

青春如此纠结 2024-09-19 17:08:56

这可能不是那么优雅,但它有效(导入/放入视图中):

import base64


def get_msg_str(msg,start):
    msg_len, _, msg_off = struct.unpack("<HHH", msg[start:start + 6])
    return msg[msg_off:msg_off + msg_len].replace("\0", '')


def ntlm_auth(request):
    """Goes through ntlm stages...
    Return user_name, response.
    While response is not none, keep sending it.
    Then use the user.
    """
    username = None
    response = None

    auth = request.META.get('HTTP_AUTHORIZATION')
    if not auth:
        response = HttpResponse(status=401)
        response['WWW-Authenticate'] = "NTLM"
    elif auth[:4] == "NTLM":
        msg = base64.b64decode(auth[4:])
        #  print repr(msg)
        ntlm_fmt = "<8sb" #string, length 8, 4 - op
        NLTM_SIG = "NTLMSSP\0"
        signature, op = struct.unpack(ntlm_fmt, msg[:9])
        if signature != NLTM_SIG:
            print "error header not recognized"
        else:
            print "recognized"
            # print signature, op
            # print repr(msg)
            if op == 1:
                out_msg_fmt = ntlm_fmt + "2I4B2Q2H"
                out_msg = struct.pack(out_msg_fmt,
                    NLTM_SIG, #Signature
                    2, #Op
                    0, #target name len
                    0, #target len off
                    1, 2, 0x81, 1, #flags
                    0, #challenge
                    0, #context
                    0, #target info len
                    0x30, #target info offset
                )

                response = HttpResponse(status=401)
                response['WWW-Authenticate'] = "NTLM " + base64.b64encode(out_msg).strip()
            elif op == 3:
                username = get_msg_str(msg, 36)

    return username, response

用法:

def my_view(request):
    username, response = ntlm_auth(request)
    if response:
        return response

我确信这可以作为装饰器变得更加优雅,并且可能还有其他方法 - 但我已经使用了它并且它有效。

This might not be that elegant, but it works (import/put into views):

import base64


def get_msg_str(msg,start):
    msg_len, _, msg_off = struct.unpack("<HHH", msg[start:start + 6])
    return msg[msg_off:msg_off + msg_len].replace("\0", '')


def ntlm_auth(request):
    """Goes through ntlm stages...
    Return user_name, response.
    While response is not none, keep sending it.
    Then use the user.
    """
    username = None
    response = None

    auth = request.META.get('HTTP_AUTHORIZATION')
    if not auth:
        response = HttpResponse(status=401)
        response['WWW-Authenticate'] = "NTLM"
    elif auth[:4] == "NTLM":
        msg = base64.b64decode(auth[4:])
        #  print repr(msg)
        ntlm_fmt = "<8sb" #string, length 8, 4 - op
        NLTM_SIG = "NTLMSSP\0"
        signature, op = struct.unpack(ntlm_fmt, msg[:9])
        if signature != NLTM_SIG:
            print "error header not recognized"
        else:
            print "recognized"
            # print signature, op
            # print repr(msg)
            if op == 1:
                out_msg_fmt = ntlm_fmt + "2I4B2Q2H"
                out_msg = struct.pack(out_msg_fmt,
                    NLTM_SIG, #Signature
                    2, #Op
                    0, #target name len
                    0, #target len off
                    1, 2, 0x81, 1, #flags
                    0, #challenge
                    0, #context
                    0, #target info len
                    0x30, #target info offset
                )

                response = HttpResponse(status=401)
                response['WWW-Authenticate'] = "NTLM " + base64.b64encode(out_msg).strip()
            elif op == 3:
                username = get_msg_str(msg, 36)

    return username, response

Usage:

def my_view(request):
    username, response = ntlm_auth(request)
    if response:
        return response

I am sure this could be made more elegant as a decorator, and there may be other ways - but I've used it and it works.

〆凄凉。 2024-09-19 17:08:56

通常,如果您只想针对 Active Directory 进行身份验证,最有可能成功的方法是针对 Active Directory LDAP 服务使用 LDAP 身份验证。唯一的技巧是,与大多数 LDAP 服务器不同,Active Directory 需要有经过身份验证的用户(和密码)。大多数人最终都会建立一个“ldap-query”用户,并对该用户进行硬编码以进行查询配置。

有关示例,请参阅 http://djangosnippets.org/snippets/501/http://www.google.com/search?q=Django+LDAP+身份验证

Generally, if you just want authentication against Active Directory, the approach most likely to succeed is to use LDAP authentication against the Active Directory LDAP service. The only trick is that unlike most LDAP servers, Active Directory needs to have an authenticated user (and password). Most folks end up establishing a 'ldap-query' user with and hardcode that user for the query configuration.

For examples, see http://djangosnippets.org/snippets/501/ and http://www.google.com/search?q=Django+LDAP+authentication

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文