File upload fails when user is authenticated. Using IIS7 Integrated mode
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)开发者_Python百科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]
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
}
}
Can you give the user Networkservice write permissions to the directories in question?
精彩评论