用户身份验证时文件上传失败。使用IIS7集成模式

发布于 2024-10-12 04:14:33 字数 1511 浏览 4 评论 0原文

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

登录: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

引用这部分:

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

当表单身份验证被使用时 应用程序和匿名访问是 允许,集成模式身份 与经典模式身份不同 通过以下方式:

* ServerVariables["LOGON_USER"] 已填充。
* Request.LogognUserIdentity 使用 [NT AUTHORITY\NETWORK SERVICE] 帐户的凭据,而不是 [NT AUTHORITY\INTERNET USER] 帐户的凭据。 

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

副作用是 LOGON_USER, HttpRequest.LogonUserIdentity,以及 冒充者无法再访问 IIS 的匿名用户凭据 7.0 将使用经典模式进行身份验证。

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

我已经四处寻找有关这个特定问题的任何答案,但到目前为止发现为零......

我希望你能提供帮助!

[碰撞]

These are the user identities my website tells me that it uses:

Logged on: NT AUTHORITY\NETWORK SERVICE (Can not write any files at all)
and
Not logged on: WSW32\IUSR_77 (Can write files to any folder)

I have a ASP.NET 4.0 website on a shared hosting IIS7 web server running in Integrated mode with 32-bit applications support enabled and MSSQL 2008. Using classic mode is not an option since I need to secure some static files and I use Routing.

In my web.config file I have set the following:

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

My hosting company says that Impersonation is enabled by default on machine level, so this is not something I can change.

I asked their support and they referred me to this article: http://www.codinghub.net/2010/08/differences-between-integrated-mode-and.html

Citing this part:

Different windows identity in Forms
authentication

When Forms Authentication is used by
an application and anonymous access is
allowed, the Integrated mode identity
differs from the Classic mode identity
in the following ways:

* 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. 

This behavior occurs because
authentication is performed in a
single stage in Integrated mode.
Conversely, in Classic mode,
authentication occurs first with IIS
7.0 using anonymous access, and then with ASP.NET using Forms
authentication. Thus, the result of
the authentication is always a single
user-- the Forms authentication user.
AUTH_USER/LOGON_USER returns this same
user because the Forms authentication
user credentials are synchronized
between IIS 7.0 and ASP.NET.

A side effect is that LOGON_USER,
HttpRequest.LogonUserIdentity, and
impersonation no longer can access the
Anonymous user credentials that IIS
7.0 would have authenticated by using Classic mode.

How do I set up my website so that it can use the proper identity with the proper permissions?

I've looked high and low for any answers regarding this specific problem, but found nil so far...

I hope you can help!

[Bump]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千年*琉璃梦 2024-10-19 04:14:33

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

使用此知识库文章“如何在 ASP.NET 应用程序中实现模拟/在代码中模拟特定用户” 我找到了一种模拟我的共享主机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
    }
}

So I finally found a solution to my problem.

Using this KB article "How to implement impersonation in an ASP.NET application / Impersonate a Specific User in Code" I found a way to impersonate my shared hosting FTP user.

This way I would gain the privileges of the said user and not compromise the security of the server by lowering the security on the NT AUTHORITY\NETWORK SERVICE user.

This is the code that I used:

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
    }
}
无远思近则忧 2024-10-19 04:14:33

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

Can you give the user Networkservice write permissions to the directories in question?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文