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

如何按规范顺序对SDDL DACL的ACE进行排序?

问题描述

我用ADSDDL库(依赖为implementation("net.tirasa:adsddl:1.9"))操作SDDL,调用SDDLHelper.userCannotChangePassword(sddl, true)启用「用户不能更改密码」标志后,在Windows ADAC(Active Directory管理中心)里收到提示,说我的ACE未按规范顺序排列,建议重新排序。查看DACL里的ACE后,发现问题出在类似(OA;;WP[16];5805bc62-bdc9-4428-a5e2-856a0f4c185e;;S-1-5-32-561)的片段——OD类型ACE出现在OA类型之后。我想解决通用排序问题并实现排序逻辑,请问哪里能找到完整的排序规则?我找到了微软官方文档,但看不懂Explicit ACEs、Deny ACEs、Regular ACEs、object ACEs这些术语的含义,怎么在代码里识别这些类型?


一、ACE规范排序规则

Windows AD对DACL内的ACE顺序有强制规范,正确排序逻辑优先级从高到低为:

  1. 显式拒绝ACE(直接给对象添加的拒绝权限)
  2. 显式允许ACE(直接给对象添加的允许权限)
  3. 继承的拒绝ACE(从父对象继承的拒绝权限)
  4. 继承的允许ACE(从父对象继承的允许权限)

同一优先级组内还要细分:

  • 先处理常规ACE,再处理对象ACE
  • 对象ACE内部,先排对象拒绝(OD),再排对象允许(OA)

二、关键ACE类型含义与代码识别(基于ADSDDL库)

1. 显式/继承ACE(Explicit/Inherited ACEs)

  • 显式ACE:直接为目标对象配置的权限,非从父容器继承
  • 继承ACE:从父容器继承而来的权限
  • 代码识别:调用ACE类的isInherited()方法,返回false为显式ACE,true为继承ACE

2. 拒绝/允许ACE(Deny/Allow ACEs)

  • 拒绝ACE:明确禁止主体的某项操作权限
  • 允许ACE:明确授予主体的某项操作权限
  • 代码识别:调用ACE类的getAceType()方法,值为AceType.ACCESS_DENIED_ACE_TYPE或AceType.ACCESS_DENIED_OBJECT_ACE_TYPE即为拒绝ACE;值为AceType.ACCESS_ALLOWED_ACE_TYPE或AceType.ACCESS_ALLOWED_OBJECT_ACE_TYPE即为允许ACE

3. 常规/对象ACE(Regular/Object ACEs)

  • 常规ACE:针对对象本身的基础权限(如读取对象基本属性),不涉及特定属性或扩展类
  • 对象ACE:针对对象特定属性、扩展属性或对象类的权限(比如你遇到的OA/OD,就是针对密码属性的对象级允许/拒绝权限)
  • 代码识别:调用ACE类的getAceType()方法,枚举值带OBJECT后缀的即为对象ACE,其余为常规ACE

三、基于ADSDDL的ACE排序实现

自定义Comparator实现规范排序:

import net.tirasa.adsddl.ntsd.ACE;
import net.tirasa.adsddl.ntsd.AceType;
import java.util.Comparator;

public class ACEComparator implements Comparator<ACE> {
    @Override
    public int compare(ACE ace1, ACE ace2) {
        // 第一步:按显式/继承+拒绝/允许划分优先级组
        int group1 = getPriorityGroup(ace1);
        int group2 = getPriorityGroup(ace2);
        if (group1 != group2) {
            return Integer.compare(group1, group2);
        }

        // 第二步:同组内先常规ACE,后对象ACE
        boolean isObjAce1 = isObjectAce(ace1);
        boolean isObjAce2 = isObjectAce(ace2);
        if (isObjAce1 != isObjAce2) {
            return isObjAce1 ? 1 : -1;
        }

        // 第三步:对象ACE内部先拒绝,后允许
        if (isObjAce1) {
            boolean isDeny1 = isDenyAce(ace1);
            boolean isDeny2 = isDenyAce(ace2);
            if (isDeny1 != isDeny2) {
                return isDeny1 ? -1 : 1;
            }
        }

        // 其余情况保持原有相对顺序
        return 0;
    }

    private int getPriorityGroup(ACE ace) {
        boolean isInherited = ace.isInherited();
        boolean isDeny = isDenyAce(ace);

        if (!isInherited && isDeny) return 1;    // 显式拒绝
        if (!isInherited && !isDeny) return 2;   // 显式允许
        if (isInherited && isDeny) return 3;     // 继承拒绝
        return 4;                                // 继承允许
    }

    private boolean isDenyAce(ACE ace) {
        AceType type = ace.getAceType();
        return type == AceType.ACCESS_DENIED_ACE_TYPE || type == AceType.ACCESS_DENIED_OBJECT_ACE_TYPE;
    }

    private boolean isObjectAce(ACE ace) {
        AceType type = ace.getAceType();
        return type == AceType.ACCESS_ALLOWED_OBJECT_ACE_TYPE || type == AceType.ACCESS_DENIED_OBJECT_ACE_TYPE;
    }
}

使用示例:

// 假设已获取目标SDDL对象
SDDL sddl = ...;
// 取出DACL的ACE列表并排序
List<ACE> aces = new ArrayList<>(sddl.getDacl().getAces());
aces.sort(new ACEComparator());
// 重新设置排序后的ACE并生成新SDDL字符串
sddl.getDacl().setAces(aces);
String sortedSddl = sddl.toString();

此逻辑会让OD类型ACE排在OA之前,完全符合ADAC的规范要求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 09:47:46