kerberos - 使用 Java 和 Kerberos 以不同用户身份创建进程
问题描述
我正在开发一个 Java 服务器应用程序(在 Windows 下作为服务运行)并希望实现以下场景:
- 用户向服务器发出 POST 请求。用户通过 Kerberos(SPNEGO、企业环境中的 SSO)进行身份验证。
- 该服务创建一个新的 Java 进程。该进程必须作为经过身份验证的用户而不是服务用户(模拟/委托)运行。
- 新进程应在用户的安全上下文中执行。它必须与需要 Kerberos 身份验证的其他远程系统通信(例如文件共享、其他 Web 服务……)。
工作概念验证:
- 用于 Kerberos 身份验证的带有Waffle的Spring Boot 应用程序。
- 为经过身份验证的用户创建一个新进程。我使用JNA和 Windows 原生函数CreateProcessAsUser。
- 该进程被创建为经过身份验证的用户。我可以使用 Process Explorer 实用程序来验证这一点。
缺少什么并且不起作用:
- 进程无法请求其他 Kerberos 票证(例如通过调用 InitializeSecurityContext())
- 该进程无法访问网络共享。
- 该进程无法与需要 Kerberos 身份验证的其他 Web 服务进行通信。
我的问题:
- 我错过了什么或我的代码可能有什么问题?
- 甚至有可能实现我想要实现的目标吗?
服务器 - 身份验证(缩短,从 Waffle 中提取):
final byte[] tokenBuffer = authorizationHeader.getTokenBytes();
CredHandle serverCredHandle = new CredHandle();
TimeStamp clientLifetime = new TimeStamp();
int rc = Secur32.INSTANCE.AcquireCredentialsHandle(
null,
"Negotiate",
Sspi.SECPKG_CRED_INBOUND,
null,
null,
null,
null,
serverCredHandle,
clientLifetime);
SecBufferDesc pbClientToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, tokenBuffer);
CtxtHandle phNewServerContext = new CtxtHandle();
SecBufferDesc pbServerToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
IntByReference pfClientContextAttr = new IntByReference();
rc = Secur32.INSTANCE.AcceptSecurityContext(
serverCredHandle,
null,
pbClientToken,
Sspi.ISC_REQ_CONNECTION,
Sspi.SECURITY_NATIVE_DREP,
phNewServerContext,
pbServerToken,
pfClientContextAttr,
null);
rc = Advapi32.INSTANCE.ImpersonateLoggedOnUser(/* provide the security context token */)
服务器 - CreateProcessAsUser:
// get impersonation token of user
WinNT.HANDLEByReference threadToken = new WinNT.HANDLEByReference();
WinNT.HANDLE threadHandle = Kernel32.INSTANCE.GetCurrentThread();
boolean threadTokenResult = Advapi32.INSTANCE.OpenThreadToken(
threadHandle,
WinNT.TOKEN_QUERY | WinNT.TOKEN_DUPLICATE | WinNT.TOKEN_ASSIGN_PRIMARY,
false, /* TRUE if the access check is to be made against the process-level security context. FALSE if the access check is to be made against the current security context of the thread calling the OpenThreadToken function. */
threadToken);
// create primary token by duplicating impersonation token
WinNT.HANDLEByReference primaryToken = new WinNT.HANDLEByReference();
boolean primaryTokenResult = Advapi32.INSTANCE.DuplicateTokenEx(
threadToken.getValue(), /* hExistingToken */
WinNT.TOKEN_DUPLICATE | WinNT.TOKEN_QUERY | WinNT.TOKEN_ASSIGN_PRIMARY, /* dwDesiredAccess */
null, /* lpTokenAttributes */
WinNT.SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, /* ImpersonationLevel */
WinNT.TOKEN_TYPE.TokenPrimary, /* TokenType */
primaryToken); /* phNewToken */
String environment = createEnvironment(primaryToken);
WinBase.STARTUPINFO startupInfo = new WinBase.STARTUPINFO();
WinBase.PROCESS_INFORMATION processInfo = new WinBase.PROCESS_INFORMATION();
boolean createProcessResult = Advapi32.INSTANCE.CreateProcessAsUser(
primaryToken.getValue(), /* hToken */
null, /* lpApplicationName */
command, /* lpCommandLine */
null, /* lpProcessAttributes */
null, /* lpThreadAttributes */
false, /* bInheritHandles */
WinNT.CREATE_NEW_CONSOLE | WinNT.CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
environment, /* lpEnvironment */
processDirectory, /* lpCurrentDirectory */
startupInfo, /* lpStartupInfo */
processInfo); /* lpProcessInformation */
解决方案
推荐阅读
- c# - 在 gRPC 中,无法将消息中的枚举值绑定到 dontnet core Dto
- node.js - 在一个简单的节点/反应应用程序中获取 Gitlab API 数据
- xaml - StringFormat 中的 Xamarin XAML 多语言
- c# - 通过 Ajax 请求超时 Umbraco Azure
- c - 异或运算的C程序,scanf输入的运算符
- meshlab - 向 Hausdorff 距离图添加图例
- javascript - 将 Array 转换为 String 再转换回 Array JavaScript 错误
- python - *(星号)可以作为文字字符传递给python吗
- mongodb - MongoTemplate聚合投影,映射数组属性时出现异常
- python - 即使通过虚拟环境安装了flask_wtf,我的程序也没有被执行