【问题标题】:File upload fails when user is authenticated. Using IIS7 Integrated mode用户通过身份验证时文件上传失败。使用 IIS7 集成模式
【发布时间】:2011-06-09 01:57:12
【问题描述】:

这些是我的网站告诉我它使用的用户身份:

登录:NT AUTHORITY\NETWORK SERVICE(根本无法写入任何文件)

未登录:WSW32\IUSR_77(可以将文件写入任何文件夹)

我在共享托管 IIS7 Web 服务器上有一个 ASP.NET 4.0 网站,该服务器以集成模式运行,启用了 32 位应用程序支持和 MSSQL 2008。使用经典模式不是一个选项,因为我需要保护一些静态文件并且我使用路由。

在我的 web.config 文件中,我设置了以下内容:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

我的托管公司说默认情况下在机器级别启用模拟,所以这不是我可以更改的。

我请求他们的支持,他们将我推荐给这篇文章:http://www.codinghub.net/2010/08/differences-between-integrated-mode-and.html

引用这部分:

Forms 中不同的窗口标识 身份验证

当表单身份验证由 一个应用程序和匿名访问是 允许,集成模式标识 不同于经典模式身份 通过以下方式:

* ServerVariables["LOGON_USER"] is filled.
* Request.LogognUserIdentity uses the credentials of the [NT AUTHORITY\NETWORK SERVICE] account instead of the [NT AUTHORITY\INTERNET USER] account. 

出现这种行为是因为 身份验证是在一个 集成模式下的单级。 相反,在经典模式下, 首先使用 IIS 进行身份验证 7.0 使用匿名访问,然后使用 ASP.NET 使用 Forms 验证。因此,结果 身份验证始终是单一的 用户——Forms 身份验证用户。 AUTH_USER/LOGON_USER 返回相同的 用户因为表单身份验证 用户凭据已同步 在 IIS 7.0 和 ASP.NET 之间。

一个副作用是 LOGON_USER, HttpRequest.LogonUserIdentity 和 模拟不再可以访问 IIS 的匿名用户凭据 7.0 将使用经典模式进行身份验证。

如何设置我的网站,以便它可以使用具有适当权限的适当身份?

对于这个特定问题的任何答案,我一直在寻找高低,但到目前为止发现为零......

希望你能帮上忙!

[]

【问题讨论】:

    标签: c# asp.net iis-7 file-upload forms-authentication


    【解决方案1】:

    所以我终于找到了解决问题的方法。

    使用这篇知识库文章"How to implement impersonation in an ASP.NET application / Impersonate a Specific User in Code",我找到了一种模拟我的共享主机FTP 用户的方法。

    这样我将获得上述用户的权限,并且不会通过降低 NT AUTHORITY\NETWORK SERVICE 用户的安全性来损害服务器的安全性。

    这是我使用的代码:

    using System;
    using System.Runtime.InteropServices;
    using System.Security.Principal;
    using System.Configuration;
    
    namespace App_Code
    {
        public class Impersonation : IDisposable
        {
            private WindowsImpersonationContext _impersonationContext;
    
            #region Win32 API Declarations
            private const int Logon32LogonInteractive = 2; //This parameter causes LogonUser to create a primary token.
            private const int Logon32ProviderDefault = 0;
    
            [DllImport("advapi32.dll")]
            private static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    
            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);
    
            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern bool RevertToSelf();
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
            private static extern bool CloseHandle(IntPtr handle);
            #endregion
    
            public bool ImpersonateDefaultFtpUser()
            {
                return ImpersonateFtpUser(ConfigurationManager.AppSettings["ftpUsername"], ConfigurationManager.AppSettings["ftpDomain"], ConfigurationManager.AppSettings["ftpPassword"]);
            }
    
            public bool ImpersonateFtpUser(string userName, string domain, string password)
            {
                WindowsIdentity tempWindowsIdentity;
                var token = IntPtr.Zero;
                var tokenDuplicate = IntPtr.Zero;
    
                if (RevertToSelf())
                {
                    if (LogonUserA(userName, domain, password, Logon32LogonInteractive, Logon32ProviderDefault, ref token) != 0)
                    {
                        if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                        {
                            tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                            _impersonationContext = tempWindowsIdentity.Impersonate();
    
                            if (_impersonationContext != null)
                            {
                                CloseHandle(token);
                                CloseHandle(tokenDuplicate);
                                return true;
                            }
                        }
                    }
                }
    
                if (token != IntPtr.Zero)
                    CloseHandle(token);
    
                if (tokenDuplicate != IntPtr.Zero)
                    CloseHandle(tokenDuplicate);
    
                return false;
            }
    
            public void UndoImpersonation()
            {
                if (_impersonationContext != null)
                    _impersonationContext.Undo();
            }
    
            /// <summary>
            /// Constructor. Impersonates the default ftp user. Impersonation lasts until
            /// the instance is disposed.
            /// </summary>
            public Impersonation()
            {
                ImpersonateDefaultFtpUser();
            }
    
            /// <summary>
            /// Constructor. Impersonates the requested user. Impersonation lasts until
            /// the instance is disposed.
            /// </summary>
            public Impersonation(string userName, string domain, string password)
            {
                ImpersonateFtpUser(userName, domain, password);
            }
    
            #region IDisposable Pattern
    
            /// <summary>
            /// Revert to original user and cleanup.
            /// </summary>
            protected virtual void Dispose(bool disposing)
            {
                if (!disposing) return;
    
                // Revert to original user identity
                UndoImpersonation();
    
                if (_impersonationContext != null)
                    _impersonationContext.Dispose();
            }
    
            /// <summary>
            /// Explicit dispose.
            /// </summary>
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            /// <summary>
            /// Destructor
            /// </summary>
            ~Impersonation()
            {
                Dispose(false);
            }
    
            #endregion
        }
    }
    

    【讨论】:

    • 你能提供更多细节吗?我遇到了同样的问题,我尝试在 标记中使用我的 FTP 凭据,但没有成功。
    • 效果很好,我只需要创建一个实例Impersonation i = new Impersonation("FTPusername","some.ip.address.v4","FTPpassword");谢谢!
    【解决方案2】:

    您能否授予用户 Networkservice 对相关目录的写入权限?

    【讨论】:

    • 我已向托管公司发送了关于网络服务身份权限的支持请求。我会在收到回复时发表评论。
    • 不继续对网络服务身份的权限。这超出了他们的安全规则,我可以理解。还有其他解决方案的建议吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 2018-11-02
    • 2017-07-25
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    相关资源
    最近更新 更多