ASP.NET Core下实现Windows用户模拟上传文件的代码示例求助
ASP.NET Core Windows身份模拟功能实现方案
前提说明
该实现仅支持在Windows操作系统上运行的ASP.NET Core应用,需先安装NuGet依赖包:System.Security.Principal.Windows
完整代码示例
using Microsoft.AspNetCore.Mvc; using System.Runtime.InteropServices; using System.Security.Principal; using Microsoft.AspNetCore.Http; public class PublicController : ControllerBase { public const int LOGON32_LOGON_INTERACTIVE = 2; public const int LOGON32_PROVIDER_DEFAULT = 0; public const int SecurityImpersonation = 2; [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool DuplicateToken(IntPtr hToken, int impersonationLevel, out IntPtr hNewToken); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool CloseHandle(IntPtr handle); [HttpPost] public IActionResult UploadFile(IFormFile file) { IntPtr token = IntPtr.Zero; IntPtr duplicateToken = IntPtr.Zero; try { // 调用LogonUser获取用户令牌 bool logonSuccess = LogonUser( userName: "someuserwithpowertoupload", domain: "", password: "somepassword", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out token); if (!logonSuccess) { return StatusCode(StatusCodes.Status500InternalServerError, "用户身份验证失败"); } // 复制令牌用于模拟 bool duplicateSuccess = DuplicateToken(token, SecurityImpersonation, out duplicateToken); if (!duplicateSuccess) { return StatusCode(StatusCodes.Status500InternalServerError, "令牌复制失败"); } // 使用WindowsIdentity.RunImpersonated执行模拟上下文内的操作 using (var identity = new WindowsIdentity(duplicateToken)) { WindowsIdentity.RunImpersonated(identity.AccessToken, () => { // 模拟上下文内执行文件保存操作 var path = "你的目标存储路径"; using (var stream = System.IO.File.Create(path)) { file.CopyTo(stream); } }); } return Ok("文件上传成功"); } catch (Exception ex) { return StatusCode(StatusCodes.Status500InternalServerError, $"上传失败:{ex.Message}"); } finally { // 释放令牌资源 if (token != IntPtr.Zero) { CloseHandle(token); } if (duplicateToken != IntPtr.Zero) { CloseHandle(duplicateToken); } } } }
关键变更说明
- .NET Core 3.0+ 移除了
WindowsImpersonationContext类,改用WindowsIdentity.RunImpersonated或异步版本RunImpersonatedAsync执行模拟上下文内的逻辑,无需手动维护上下文和执行回滚操作,方法执行完成后会自动恢复原进程身份 - LogonUser API统一使用Unicode版本
LogonUser替代原ANSI版本LogonUserA,避免字符编码问题
注意事项
- 运行应用的进程身份需要拥有"作为操作系统的一部分"、"允许本地登录"等权限,若部署在IIS中需要对应配置应用池身份的权限
- 本地用户模拟时domain参数填""或"."即可,域用户需要填写对应的域名
- 令牌资源必须在finally块中手动释放,避免出现资源泄漏
内容的提问来源于stack exchange,提问作者blue piranha
相关产品推荐
相关产品推荐

