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

Java向Samba Active Directory添加用户时名称显示异常求助

问题:向Samba AD添加用户后,用户名显示为$BE23343...异常字符串

通过Java编写的图形界面程序向Samba Active Directory添加用户时,操作可正常执行,但用户在AD中显示的名称为$BE23343...这类随机异常字符串。以下是相关代码:

import javax.naming.*;
import javax.naming.directory.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Hashtable;

public class ADManagerUI extends JFrame {

    private static final long serialVersionUID = 1L;
    private JTextField cnField;
    private JTextField snField;
    private JTextField uidField;
    private JTextField passwordField;
    private JTextField mailField;
    private JTextField displayNameField;
    private JTextField descriptionField;
    private JButton addButton;
    private JButton deleteButton;
    private JButton modifyButton;


    public ADManagerUI() {
        // 初始化窗口
        setTitle("AD用户管理器");
        setSize(600, 400);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // 创建文本框和标签
        JLabel cnLabel = new JLabel("全名:");
        cnField = new JTextField(20);
        JLabel snLabel = new JLabel("姓氏:");
        snField = new JTextField(20);
        JLabel uidLabel = new JLabel("用户名:");
        uidField = new JTextField(20);
        JLabel passwordLabel = new JLabel("密码:");
        passwordField = new JTextField(20);
        JLabel mailLabel = new JLabel("邮箱地址:");
        mailField = new JTextField(20);
        JLabel displayNameLabel = new JLabel("显示名称:");
        displayNameField = new JTextField(20);
        JLabel descriptionLabel = new JLabel("描述:");
        descriptionField = new JTextField(20);

        // 创建按钮
        addButton = new JButton("添加用户");
        deleteButton = new JButton("删除用户");
        modifyButton = new JButton("修改用户");

        // 将文本框和标签添加到窗口
        setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.anchor = GridBagConstraints.WEST;
        constraints.insets = new Insets(5, 5, 5, 5);
        constraints.gridx = 0;
        constraints.gridy = 0;
        add(cnLabel, constraints);
        constraints.gridx = 1;
        add(cnField, constraints);
        constraints.gridx = 0;
        constraints.gridy = 1;
        add(snLabel, constraints);
        constraints.gridx = 1;
        add(snField, constraints);
        constraints.gridx = 0;
        constraints.gridy = 2;
        add(uidLabel, constraints);
        constraints.gridx = 1;
        add(uidField, constraints);
        constraints.gridx = 0;
        constraints.gridy = 3;
        add(passwordLabel, constraints);
        constraints.gridx = 1;
        add(passwordField, constraints);
        constraints.gridx = 0;
        constraints.gridy = 4;
        add(mailLabel, constraints);
        constraints.gridx = 1;
        add(mailField, constraints);
        constraints.gridx = 0;
        constraints.gridy = 5;
        add(displayNameLabel, constraints);
        constraints.gridx = 1;
        add(displayNameField, constraints);
        constraints.gridx = 0;
        constraints.gridy = 6;
        add(descriptionLabel, constraints);
        constraints.gridx = 1;
        add(descriptionField, constraints);
        // 将按钮添加到窗口
        constraints.gridx = 0;
        constraints.gridy = 8;
        add(addButton, constraints);
        constraints.gridx = 1;
        add(deleteButton, constraints);
        constraints.gridx = 2;
        add(modifyButton, constraints);
        // 为按钮添加监听器
        addButton.addActionListener(new AddButtonListener());
        deleteButton.addActionListener(new DeleteButtonListener());
        modifyButton.addActionListener(new ModifyButtonListener());
    }

    // 内部类处理"添加"按钮点击事件
    class AddButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            // LDAP服务器连接信息
            String ldapAdServer = "ldap://serveur.domaine.com";
            String ldapUsername = "cn=admin,dc=domaine,dc=com";
            String ldapPassword = "mot_de_passe";

            // 新用户信息
            String cn = cnField.getText();
            String sn = snField.getText();
            String uid = uidField.getText();
            String password = passwordField.getText();
            String mail = mailField.getText();
            String displayName = displayNameField.getText();
            String description = descriptionField.getText();

            // 连接LDAP服务器
            Hashtable<String, Object> env = new Hashtable<String, Object>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, ldapAdServer);
            env.put(Context.SECURITY_PRINCIPAL, ldapUsername);
            env.put(Context.SECURITY_CREDENTIALS, ldapPassword);

            try {
                // 创建LDAP上下文
                DirContext ctx = new InitialDirContext(env);

                // 创建新用户条目
                Attributes attrs = new BasicAttributes();
                Attribute objClasses = new BasicAttribute("objectClass");
                objClasses.add("top");
                objClasses.add("person");
                objClasses.add("organizationalPerson");
                objClasses.add("user");
                attrs.put(objClasses);
                attrs.put(new BasicAttribute("cn", cn));
                attrs.put(new BasicAttribute("sn", sn));
                attrs.put(new BasicAttribute("uid", uid));
                attrs.put(new BasicAttribute("userPassword", password));
                attrs.put(new BasicAttribute("mail", mail));
                attrs.put(new BasicAttribute("displayName", displayName));
                attrs.put(new BasicAttribute("description", description));

                String dn = "cn=" + cn + ",ou=utilisateurs,dc=domaine,dc=com";
                ctx.createSubcontext(dn, attrs);
                ctx.close();

                JOptionPane.showMessageDialog(null, "用户添加成功!");
            } catch (NamingException ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(null, "添加用户时出错!");
            }
        }
    }

    // 补充缺失的监听器实现
    class DeleteButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {}
    }

    class ModifyButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {}
    }

    public static void main(String[] args) {
        ADManagerUI adUI = new ADManagerUI();
        adUI.setVisible(true);
    }
}

问题原因分析

  1. 缺失AD核心属性sAMAccountName:
    Samba AD和Windows AD都依赖sAMAccountName作为用户的登录标识符和显示名称的核心属性。当前代码仅设置了LDAP标准属性uid,但AD不会自动将uid映射为sAMAccountName,当该属性缺失时,AD会自动生成一个以$开头的随机字符串作为默认值,这就是你看到的异常显示内容。

  2. 密码属性设置错误:
    AD不使用userPassword存储密码,而是使用UnicodePwd,且需要特定格式:密码必须用双引号包裹,再转换为UTF-16LE编码的字节数组。直接设置明文userPassword会导致密码无法正常生效。

修复方案

修改AddButtonListener中的属性设置逻辑,添加sAMAccountName并修复密码处理:

// 内部类处理"添加"按钮点击事件
class AddButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        // LDAP服务器连接信息
        String ldapAdServer = "ldap://serveur.domaine.com";
        String ldapUsername = "cn=admin,dc=domaine,dc=com";
        String ldapPassword = "mot_de_passe";

        // 新用户信息
        String cn = cnField.getText();
        String sn = snField.getText();
        String uid = uidField.getText();
        // 建议sAMAccountName与uid保持一致,需符合AD命名规则
        String samAccountName = uid;
        String password = passwordField.getText();
        String mail = mailField.getText();
        String displayName = displayNameField.getText();
        String description = descriptionField.getText();

        // 连接LDAP服务器
        Hashtable<String, Object> env = new Hashtable<String, Object>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, ldapAdServer);
        env.put(Context.SECURITY_PRINCIPAL, ldapUsername);
        env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
        // 设置认证方式
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        // 若AD要求SSL连接,需开启以下配置并使用ldaps://地址
        // env.put("java.naming.ldap.factory.socket", "javax.net.ssl.SSLSocketFactory");

        try {
            // 创建LDAP上下文
            DirContext ctx = new InitialDirContext(env);

            // 创建新用户条目
            Attributes attrs = new BasicAttributes();
            Attribute objClasses = new BasicAttribute("objectClass");
            objClasses.add("top");
            objClasses.add("person");
            objClasses.add("organizationalPerson");
            objClasses.add("user");
            attrs.put(objClasses);
            attrs.put(new BasicAttribute("cn", cn));
            attrs.put(new BasicAttribute("sn", sn));
            attrs.put(new BasicAttribute("uid", uid));
            // 添加AD必需的sAMAccountName属性
            attrs.put(new BasicAttribute("sAMAccountName", samAccountName));
            attrs.put(new BasicAttribute("mail", mail));
            attrs.put(new BasicAttribute("displayName", displayName));
            attrs.put(new BasicAttribute("description", description));

            // 处理AD密码:双引号包裹后转UTF-16LE编码
            String quotedPassword = "\"" + password + "\"";
            byte[] unicodePassword = quotedPassword.getBytes("UTF-16LE");
            attrs.put(new BasicAttribute("UnicodePwd", unicodePassword));

            // 可选:设置用户为启用状态(512为启用,514为禁用)
            attrs.put(new BasicAttribute("userAccountControl", "512"));

            String dn = "cn=" + cn + ",ou=utilisateurs,dc=domaine,dc=com";
            ctx.createSubcontext(dn, attrs);
            ctx.close();

            JOptionPane.showMessageDialog(null, "用户添加成功!");
        } catch (Exception ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(null, "添加用户时出错:" + ex.getMessage());
        }
    }
}

额外注意事项

  • sAMAccountName命名规则:长度不超过20字符,不能包含/ \ [ ] : ; | = , + * ? < >等特殊字符。
  • 加密连接要求:设置UnicodePwd时,AD通常要求使用LDAPS(端口636)或StartTLS加密连接,否则会抛出操作不允许的异常。
  • 用户状态控制:默认创建的用户可能处于禁用状态,通过userAccountControl属性可设置启用/禁用状态。

内容的提问来源于stack exchange,提问作者bertrand pacode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 23:05:17