为何IIS上C# Web应用可访问网络共享,C++编写的ISAPI扩展却不行?
IIS 10下C# Web应用与C++ ISAPI扩展访问网络共享行为差异原因及解决方案
二者行为不一致的核心原因
- C# ASP.NET托管应用默认继承IIS身份模拟逻辑:IIS 10环境下的托管Web应用默认会启用站点配置的身份模拟特性,会自动使用请求用户身份或应用池配置的托管身份上下文访问网络资源,Windows身份验证票据会自动传递,无需手动处理身份切换逻辑,因此可以直接访问网络共享。
- C++ ISAPI原生扩展默认无自动身份模拟逻辑:ISAPI扩展作为非托管程序,默认运行在w3wp.exe工作进程的基础安全上下文内,该上下文默认是
IIS AppPool\你的应用池名称这类本地虚拟账户,没有域网络资源的访问权限,也不会自动继承请求用户的身份上下文,因此默认无法访问网络共享文件。
现有ImpersonateLoggedOnUser方案的落地建议
你已经验证过ImpersonateLoggedOnUser可解决访问问题,配合加密存储凭据的方案可以按以下规范实现:
- 加密存储凭据:将可访问目标共享的域账号、密码存储在数据库的加密列中,禁止明文存储;加密密钥需保存在Windows凭据管理器或仅应用池身份可读取的加密配置节点中,禁止硬编码在代码内。
- 代码实现注意事项:
- 读取解密凭据后,先调用
LogonUser接口生成用户令牌,登录类型选择LOGON32_LOGON_NETWORK,登录提供器选择LOGON32_PROVIDER_WINNT50适配跨域网络资源访问场景。 - 调用
ImpersonateLoggedOnUser切换安全上下文后,再执行网络共享文件的读写操作。 - 文件操作完成后必须调用
RevertToSelf接口切回原安全上下文,避免上下文泄漏导致后续请求出现权限异常。 - 所有Windows API调用后需校验返回值,令牌句柄使用完成后调用
CloseHandle释放,避免资源泄漏。
- 读取解密凭据后,先调用
无凭据存储的备选方案
如果不需要针对不同请求切换访问身份,也可以直接调整应用池配置无需修改代码:将ISAPI扩展所属站点的应用池运行身份,修改为拥有目标网络共享访问权限的域账号,即可直接访问共享资源,适合不需要动态切换访问身份的场景。
内容的提问来源于stack exchange,提问作者Roland Smith
相关产品推荐
相关产品推荐

