You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Django搭建用户自助修改Active Directory密码的网页

绝对可以实现!我之前帮公司搭建过一模一样的自助域密码重置系统,帮管理员省了超多处理重置请求的时间。下面给你一步步拆解实现方案:

核心思路与依赖选择

要让Django对接Active Directory,我们需要用Python的LDAP操作库来和AD交互。这里推荐ldap3——它是现代、跨平台的LDAP客户端,比老旧的pyad更灵活,而且不需要依赖Windows环境。

实现步骤与关键代码

1. 安装依赖

先把需要的包装起来:

pip install ldap3 django

2. 配置AD连接信息

在Django的settings.py里添加AD相关配置(记得把占位符换成你的实际信息):

# settings.py
AD_SERVER = 'your-ad-server.example.com'  # AD服务器地址或域名
AD_DOMAIN = 'EXAMPLE'  # 域前缀(比如你的域是example.com,这里填EXAMPLE)
AD_SERVICE_ACCOUNT = 'ad_service_account@example.com'  # 有修改密码权限的服务账号
AD_SERVICE_PASSWORD = 'your-service-account-password'  # 服务账号密码
AD_SEARCH_BASE = 'OU=CompanyUsers,DC=example,DC=com'  # 用户所在的OU的LDAP路径

3. 编写AD操作工具类

新建一个ad_utils.py文件,封装AD验证和密码修改的逻辑:

from ldap3 import Server, Connection, ALL, MODIFY_REPLACE
from django.conf import settings

def authenticate_ad_user(username, password):
    """验证用户当前AD密码是否正确"""
    server = Server(settings.AD_SERVER, get_info=ALL)
    try:
        # 用用户自己的账号密码绑定AD,验证身份
        conn = Connection(server, user=f"{settings.AD_DOMAIN}\\{username}", password=password, auto_bind=True)
        conn.unbind()
        return True
    except Exception as e:
        print(f"身份验证失败: {str(e)}")
        return False

def change_ad_user_password(username, new_password):
    """修改AD用户密码"""
    server = Server(settings.AD_SERVER, get_info=ALL)
    try:
        # 用服务账号连接AD(必须有修改用户密码的权限)
        conn = Connection(server, user=settings.AD_SERVICE_ACCOUNT, password=settings.AD_SERVICE_PASSWORD, auto_bind=True)
        
        # 搜索用户的LDAP区分名(DN)
        conn.search(
            search_base=settings.AD_SEARCH_BASE,
            search_filter=f"(sAMAccountName={username})",
            attributes=['distinguishedName']
        )
        if not conn.entries:
            conn.unbind()
            return False, "未找到该域账号"
        
        user_dn = conn.entries[0].distinguishedName.value
        
        # AD要求密码转成UTF-16LE字节串,并用双引号包裹
        encoded_password = f'"{new_password}"'.encode('utf-16-le')
        
        # 执行密码修改操作
        conn.modify(
            user_dn,
            {'unicodePwd': [(MODIFY_REPLACE, [encoded_password])]}
        )
        
        if conn.result['result'] == 0:
            conn.unbind()
            return True, "密码修改成功!"
        else:
            conn.unbind()
            return False, f"修改失败: {conn.result['description']}"
    except Exception as e:
        return False, f"连接AD服务器失败: {str(e)}"

4. 编写Django视图与表单

在views.py里处理用户的密码修改请求:

from django.shortcuts import render, redirect
from django.contrib import messages
from django import forms
from .ad_utils import authenticate_ad_user, change_ad_user_password

# 定义密码修改表单
class PasswordChangeForm(forms.Form):
    username = forms.CharField(label='域账号', max_length=50)
    current_password = forms.CharField(label='当前密码', widget=forms.PasswordInput)
    new_password = forms.CharField(label='新密码', widget=forms.PasswordInput)
    confirm_new_password = forms.CharField(label='确认新密码', widget=forms.PasswordInput)
    
    def clean(self):
        cleaned_data = super().clean()
        new_pwd = cleaned_data.get('new_password')
        confirm_pwd = cleaned_data.get('confirm_new_password')
        
        # 验证两次密码一致
        if new_pwd != confirm_pwd:
            raise forms.ValidationError("新密码与确认密码不匹配")
        # 这里可以加和AD一致的密码复杂度验证(比如长度≥8、包含大小写等)
        if len(new_pwd) < 8:
            raise forms.ValidationError("密码长度至少为8位")
        return cleaned_data

def password_change(request):
    if request.method == 'POST':
        form = PasswordChangeForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            current_pwd = form.cleaned_data['current_password']
            new_pwd = form.cleaned_data['new_password']
            
            # 先验证当前密码是否正确
            if authenticate_ad_user(username, current_pwd):
                # 验证通过,执行密码修改
                success, msg = change_ad_user_password(username, new_pwd)
                if success:
                    messages.success(request, msg)
                    return redirect('password_change')
                else:
                    messages.error(request, msg)
            else:
                messages.error(request, "当前密码不正确,请重新输入")
    else:
        form = PasswordChangeForm()
    return render(request, 'password_change.html', {'form': form})

5. 编写前端模板

新建templates/password_change.html页面:

<!DOCTYPE html>
<html>
<head>
    <title>域密码自助修改</title>
    <style>
        .success { color: green; }
        .error { color: red; }
    </style>
</head>
<body>
    <h1>域密码自助修改</h1>
    {% if messages %}
        {% for message in messages %}
            <div class="{{ message.tags }}">{{ message }}</div>
        {% endfor %}
    {% endif %}
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">确认修改</button>
    </form>
</body>
</html>
关键注意事项
  • 服务账号权限:一定要确保你用的AD服务账号有“重置用户密码”的权限,可以在AD管理器里给该账号分配对应OU的权限。
  • 安全防护:
    • 网站必须用HTTPS部署,避免密码明文传输;
    • 可以添加验证码功能,防止暴力破解;
    • 记录所有密码修改操作日志,方便审计。
  • 密码策略对齐:前端/后端的密码复杂度验证要和AD的域密码策略保持一致,避免用户输入不符合要求的密码导致修改失败。

内容的提问来源于stack exchange,提问作者KalicXing Njenga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:04:09