KerbRetrieveEncodedTicketMessage约束委派失败:LsaCallAuthenticationPackage报错2148074254
解决LsaCallAuthenticationPackage在约束委派下报错STATUS_LOGON_SESSION_NOT_FOUND(2148074254)的问题
首先,这个错误码2148074254对应的是Windows的STATUS_LOGON_SESSION_NOT_FOUND,本质是约束委派的严格规则导致你的登录会话无法被LSA验证通过——这和非约束委派的宽松模式有本质区别。我结合过往处理Kerberos委派的经验,给你几个核心排查方向:
1. 先确认约束委派的AD配置完全正确
约束委派比非约束要精细得多,少一个环节都不行:
- 检查你用来委派的账户(比如服务账户)的AD属性:是否勾选了**“仅信任此用户指定的服务”**,并且在下方的服务列表里准确添加了目标服务的SPN(比如
HTTP/webserver.domain.com),不能有拼写错误,也不能漏加。 - 目标服务的运行账户(比如webserver的域账户/计算机账户)必须允许被委派:如果是计算机账户,要确保它的AD属性里没有勾选“不允许委派”。
2. 验证模拟的登录会话有效性
约束委派要求你用来模拟的Windows身份会话必须是合法且符合委派条件的:
- 你是用
LogonUser还是其他API创建的模拟令牌?要确保这个令牌对应的登录会话没有过期、没有被终止,并且在调用LsaCallAuthenticationPackage时,正确传递了会话ID(比如通过LsaRegisterLogonSession关联到LSA上下文)。 - 非约束委派可能允许你用任意有效会话,但约束委派要求这个会话的用户必须是被允许通过委派访问目标服务的,比如用户所在的组是否有对应权限。
3. 检查KERB_RETRIEVE_TKT_REQUEST的参数设置
在约束委派场景下,这个结构体的参数不能像非约束那样随意:
- 必须明确指定
TargetName为你在AD委派配置里允许的那个SPN,不能留空或者填TGT的SPN(krbtgt/domain.com)——约束委派不允许获取TGT,只能获取指定服务的票据,这是关键区别! - 确保
MessageType确实是KerbRetrieveEncodedTicketMessage,并且LogonId和你模拟的登录会话ID完全匹配。
举个约束委派下的参数示例:
KERB_RETRIEVE_TKT_REQUEST request = {0}; request.MessageType = KerbRetrieveEncodedTicketMessage; request.LogonId = simulatedLogonId; // 模拟会话的ID request.TargetName = L"HTTP/webserver.domain.com"; // 必须是AD里允许的SPN request.TicketFlags = KERB_RETRIEVE_TICKET_USE_CACHE;
4. 确认LSA上下文的绑定关系
调用LsaCallAuthenticationPackage前,你的LSA上下文必须正确关联到模拟的登录会话:
- 如果是用
LsaConnectUntrusted创建的上下文,可能需要额外调用LsaRegisterLogonSession来把模拟令牌的会话ID注册到LSA,否则约束委派的验证会找不到对应的会话。 - 避免在不同线程或者不同进程间传递LSA上下文,因为会话绑定是进程内的,跨进程会导致会话无法被识别。
5. 权限排查
执行代码的账户本身需要足够的权限:
- 必须是域内的账户,并且被AD授予了对应的约束委派权限(也就是前面说的AD配置)。
- 如果是本地系统账户运行的服务,要确保它的计算机账户在AD里有正确的委派配置,而不是用本地用户。
如果还是有问题,可以尝试用klist命令查看当前会话的票据,确认模拟会话是否有有效的Kerberos票据基础,或者用ADSI编辑器检查委派配置的细节,有没有隐藏的配置错误。
内容的提问来源于stack exchange,提问作者mlg
相关产品推荐
相关产品推荐

