内网Django Web应用集成Active Directory实现免密登录及信息获取咨询
实现Django内网AD免密登录及用户信息获取
咱们要搞定的是内网环境下基于Kerberos/NTLM的免密登录——让已经登录AD域的用户打开网站时自动完成认证,不用重复输密码,同时还要拉取他们的AD详细信息。下面是一步步可落地的方案:
一、先搭好核心依赖
先安装几个关键的Python包,这些是实现功能的基础:
django-auth-kerberos:专门处理Kerberos认证,是免密登录的核心ldap3:用来连接AD服务器,查询用户的详细属性(部门、邮箱、职位等)pywin32(如果Django服务器是Windows系统):辅助处理Windows环境下的Kerberos相关操作
用pip一键安装:
pip install django-auth-kerberos ldap3 pywin32
二、配置Kerberos认证(实现免密登录)
1. 服务器端配置Kerberos客户端
如果是Linux服务器:
- 先装Kerberos工具包:
sudo apt-get install krb5-user - 编辑
/etc/krb5.conf,填入你的AD域信息:
[libdefaults] default_realm = YOUR_DOMAIN.COM dns_lookup_realm = true dns_lookup_kdc = true [realms] YOUR_DOMAIN.COM = { kdc = ad.your_domain.com # AD服务器的KDC地址 admin_server = ad.your_domain.com } [domain_realm] .your_domain.com = YOUR_DOMAIN.COM your_domain.com = YOUR_DOMAIN.COM
如果是Windows服务器:
确保服务器已经加入AD域,或者至少能通过DNS正常解析到AD的KDC服务器。
2. 创建AD服务主体并生成keytab文件
这一步是让Django服务能和AD的Kerberos系统互认:
- 在AD服务器上,用管理员权限运行CMD,注册服务主体名称(SPN):
setspn -A HTTP/your-django-server.your_domain.com YOUR_DOMAIN\django_service_account
(django_service_account是你为Django服务创建的AD账号,也可以用现有账号)
- 生成keytab文件(Django服务用来验证身份的密钥文件):
ktpass /princ HTTP/your-django-server.your_domain.com@YOUR_DOMAIN.COM /mapuser YOUR_DOMAIN\django_service_account /pass * /out django.keytab /ptype KRB5_NT_PRINCIPAL
把生成的django.keytab传到Django服务器上,给运行Django的用户设置读取权限。
3. 配置Django的settings.py
在项目的settings.py里添加认证后端和Kerberos相关配置:
# 追加认证后端,优先用Kerberos AUTHENTICATION_BACKENDS = [ 'django_auth_kerberos.backends.KerberosBackend', 'django.contrib.auth.backends.ModelBackend', # 保留默认后端方便测试 ] # Kerberos核心配置 KERBEROS_REALM = 'YOUR_DOMAIN.COM' KERBEROS_SERVICE_PRINCIPAL = 'HTTP/your-django-server.your_domain.com@YOUR_DOMAIN.COM' KERBEROS_KEYTAB = '/path/to/django.keytab' # Linux路径,Windows用'C:\\django.keytab' # 可选:自动创建不存在的Django用户 KERBEROS_CREATE_USER = True KERBEROS_USERNAME_SUFFIX = '@YOUR_DOMAIN.COM' # 去掉域名后缀,比如把user@DOMAIN.COM变成user
4. 添加认证中间件
在settings.py的MIDDLEWARE列表里加入Negotiate中间件,让Django能处理客户端的Kerberos请求:
MIDDLEWARE = [ # ... 其他原有中间件 'django_auth_kerberos.middleware.NegotiateMiddleware', ]
三、获取AD用户详细信息
用户通过Kerberos认证后,我们可以用ldap3连接AD服务器,查询用户的各类详情。
1. 编写AD查询工具函数
在项目里新建一个工具文件(比如ad_utils.py),封装查询逻辑:
from ldap3 import Server, Connection, ALL, SUBTREE from django.conf import settings def get_ad_user_details(username): # 连接AD服务器 ad_server = Server(settings.AD_SERVER, get_info=ALL) conn = Connection( ad_server, user=f'{settings.AD_SERVICE_ACCOUNT}@{settings.AD_REALM}', password=settings.AD_SERVICE_PASSWORD, auto_bind=True ) # 查询用户属性,过滤条件和属性列表可根据你的AD结构调整 search_filter = f'(sAMAccountName={username})' attributes = ['cn', 'mail', 'department', 'telephoneNumber', 'title', 'memberOf'] conn.search( search_base=settings.AD_SEARCH_BASE, search_filter=search_filter, search_scope=SUBTREE, attributes=attributes ) if conn.entries: user_entry = conn.entries[0] return { 'full_name': user_entry.cn.value, 'email': user_entry.mail.value if hasattr(user_entry, 'mail') else None, 'department': user_entry.department.value if hasattr(user_entry, 'department') else None, 'phone': user_entry.telephoneNumber.value if hasattr(user_entry, 'telephoneNumber') else None, 'title': user_entry.title.value if hasattr(user_entry, 'title') else None, 'groups': [group.split(',')[0].split('=')[1] for group in user_entry.memberOf] if hasattr(user_entry, 'memberOf') else [] } return None
2. 在settings.py里添加AD查询配置
AD_SERVER = 'ad.your_domain.com' # AD服务器地址 AD_REALM = 'YOUR_DOMAIN.COM' AD_SERVICE_ACCOUNT = 'django_service_account' # 用来查询AD的服务账号 AD_SERVICE_PASSWORD = 'your_service_account_password' AD_SEARCH_BASE = 'DC=your_domain,DC=com' # AD的搜索根节点,比如域是your_domain.com就填这个
3. 在视图中调用展示
比如在用户个人中心视图里:
from django.shortcuts import render from django.contrib.auth.decorators import login_required from .ad_utils import get_ad_user_details @login_required def user_profile(request): ad_details = get_ad_user_details(request.user.username) return render(request, 'profile.html', {'ad_details': ad_details})
然后在模板profile.html里展示信息:
<h2>你的AD账户信息</h2> {% if ad_details %} <p>姓名: {{ ad_details.full_name }}</p> <p>邮箱: {{ ad_details.email }}</p> <p>部门: {{ ad_details.department }}</p> <p>职位: {{ ad_details.title }}</p> <p>所属组: {{ ad_details.groups|join:', ' }}</p> {% else %} <p>暂时无法获取AD信息,请联系管理员</p> {% endif %}
四、测试与注意事项
- 确保客户端和Django服务器在同一个AD域或信任域内,且客户端已登录AD账号
- 现代浏览器(如Chrome)默认限制HTTP下的Negotiate认证,生产环境建议部署HTTPS;测试时可在Chrome的
chrome://net-internals/#hsts里添加服务器域名 - 如果Kerberos认证失败,可查看Django日志,或用
kinit命令测试服务账号的票据获取是否正常
内容的提问来源于stack exchange,提问作者Saurabh Lall
相关产品推荐
相关产品推荐

