ASP.NET:以域用户身份访问网络资源
using System;
using System.IO;
using
System.Security.Principal;
using System.ComponentModel;
using
System.Configuration;
using System.Runtime.InteropServices;
namespace
AD.Data
{
public delegate void FileOSExecution(params
object[] Data);
public static class
FileOS
{
private static readonly String FileUploadUser =
"User";
private static readonly
String FileUploadPassword =
"password";
private static
readonly String FileUploadUserDomain =
"domain";
public static void
Execute(FileOSExecution fileOSExecution, out Exception Error, params object[]
Data)
{
Error =
null;
IntPtr token =
IntPtr.Zero;
IntPtr tokenDuplicate =
IntPtr.Zero;
try
{
if
(!NativeMethods.LogonUser(
FileUploadUser,
FileUploadUserDomain,
FileUploadPassword,
NativeMethods.LogonType.NewCredentials,
NativeMethods.LogonProvider.Default,
out
token))
{
Error = new Win32Exception("User Logon
Error");
return;
}
if
(!NativeMethods.DuplicateToken(
token,
NativeMethods.SecurityImpersonationLevel.Impersonation,
out
tokenDuplicate))
{
Error = new Win32Exception("Duplicate Token
Error");
return;
}
using (WindowsImpersonationContext impersonationContext
=
new
WindowsIdentity(tokenDuplicate).Impersonate())
{
try
{
fileOSExecution(Data);
}
catch (Exception
e)
{
Error =
e;
}
impersonationContext.Undo();
}
}
finally
{
if (tokenDuplicate !=
IntPtr.Zero)
NativeMethods.CloseHandle(tokenDuplicate);
if (token !=
IntPtr.Zero)
NativeMethods.CloseHandle(token);
}
}
}
/// <summary>
///
Implements P/Invoke Interop calls to the operating system.
/// </summary>
internal static class
NativeMethods
{
///
<summary>
/// The type of
logon operation to perform.
///
</summary>
internal enum
LogonType : int
{
///
<summary>
/// This logon type is intended for users who will be
interactively
/// using the computer, such as a user being logged on by
a
///
terminal server, remote shell, or similar
process.
/// This logon type has the additional expense of caching
logon
///
information for disconnected operations; therefore, it
is
///
inappropriate for some client/server applications, such as
a
/// mail
server.
///
</summary>
Interactive =
2,
///
<summary>
/// This logon type is intended for high performance servers
to
///
authenticate plaintext
passwords.
/// The LogonUser function does not cache credentials for
this
///
logon
type.
///
</summary>
Network =
3,
///
<summary>
/// This logon type is intended for batch servers, where
processes
/// may be executing on behalf of a user without their
direct
///
intervention. This type is also for higher performance
servers
/// that process many plaintext authentication attempts at a
time,
///
such as mail or Web
servers.
/// The LogonUser function does not cache credentials for
this
///
logon
type.
///
</summary>
Batch =
4,
///
<summary>
/// Indicates a service-type logon. The account provided must
have
///
the service privilege
enabled.
///
</summary>
Service =
5,
///
<summary>
/// This logon type is for GINA DLLs that log on users who will
be
///
interactively using the
computer.
/// This logon type can generate a unique audit record that
shows
///
when the workstation was
unlocked.
///
</summary>
Unlock =
7,
///
<summary>
/// This logon type preserves the name and password in
the
///
authentication package, which allows the server to
make
///
connections to other network servers while impersonating
the
///
client. A server can accept plaintext credentials from
a
///
client, call LogonUser, verify that the user can access
the
///
system across the network, and still communicate with
other
///
servers.
/// NOTE: Windows NT: This value is not
supported.
///
</summary>
NetworkCleartext =
8,
///
<summary>
/// This logon type allows the caller to clone its current
token
///
and specify new credentials for outbound connections. The
new
///
logon session has the same local identifier but uses
different
/// credentials for other network
connections.
/// NOTE: This logon type is supported only by
the
///
LOGON32_PROVIDER_WINNT50 logon
provider.
/// NOTE: Windows NT: This value is not
supported.
///
</summary>
NewCredentials = 9
}
///
<summary>
/// Specifies the
logon provider.
///
</summary>
internal enum
LogonProvider : int
{
///
<summary>
/// Use the standard logon provider for the
system.
/// The default security provider is negotiate, unless you
pass
///
NULL for the domain name and the user name is not in UPN
format.
/// In this case, the default provider is
NTLM.
///
NOTE: Windows 2000/NT: The default security provider is
NTLM.
///
</summary>
Default =
0,
///
<summary>
/// Use this provider if you‘ll be authenticating against a
Windows
/// NT 3.51 domain controller (uses the NT 3.51 logon
provider).
///
</summary>
WinNT35 =
1,
///
<summary>
/// Use the NTLM logon
provider.
///
</summary>
WinNT40 =
2,
///
<summary>
/// Use the negotiate logon
provider.
///
</summary>
WinNT50 = 3
}
///
<summary>
/// The type of
logon operation to perform.
///
</summary>
internal enum
SecurityImpersonationLevel : int
{
///
<summary>
/// The server process cannot obtain identification
information
/// about the client, and it cannot impersonate the client. It
is
///
defined with no value given, and thus, by ANSI C
rules,
///
defaults to a value of
zero.
///
</summary>
Anonymous =
0,
///
<summary>
/// The server process can obtain information about the
client,
/// such as security identifiers and privileges, but it
cannot
///
impersonate the client. This is useful for servers that
export
///
their own objects, for example, database products that
export
///
tables and views. Using the retrieved
client-security
/// information, the server can make access-validation
decisions
/// without being able to use other services that are using
the
///
client‘s security
context.
///
</summary>
Identification =
1,
///
<summary>
/// The server process can impersonate the client‘s
security
/// context on its local system. The server cannot impersonate
the
///
client on remote
systems.
///
</summary>
Impersonation =
2,
///
<summary>
/// The server process can impersonate the client‘s
security
/// context on remote
systems.
/// NOTE: Windows NT: This impersonation level is not
supported.
///
</summary>
Delegation = 3
}
///
<summary>
/// Logs on the
user.
///
</summary>
/// <param
name="userName">Name of the
user.</param>
/// <param
name="domain">The
domain.</param>
///
<param name="password">The
password.</param>
///
<param name="logonType">Type of the
logon.</param>
/// <param
name="logonProvider">The logon
provider.</param>
///
<param name="token">The
token.</param>
///
<returns>True if the function succeeds, false if the function
fails.
/// To get extended error
information, call
GetLastError.</returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError =
true)]
[return:
MarshalAs(UnmanagedType.Bool)]
internal static extern bool
LogonUser(
string
userName,
string
domain,
string
password,
LogonType
logonType,
LogonProvider
logonProvider,
out IntPtr token);
///
<summary>
/// Duplicates the
token.
///
</summary>
/// <param
name="existingTokenHandle">The existing
token
///
handle.</param>
///
<param name="securityImpersonationLevel">The security
impersonation
///
level.</param>
/// <param
name="duplicateTokenHandle">The duplicate
token
///
handle.</param>
///
<returns>True if the function succeeds, false if the function
fails.
/// To get extended error
information, call
GetLastError.</returns>
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError =
true)]
[return:
MarshalAs(UnmanagedType.Bool)]
internal static extern bool
DuplicateToken(
IntPtr
existingTokenHandle,
SecurityImpersonationLevel
securityImpersonationLevel,
out IntPtr
duplicateTokenHandle);
///
<summary>
/// Closes the
handle.
///
</summary>
/// <param
name="handle">The
handle.</param>
///
<returns>True if the function succeeds, false if the function
fails.
/// To get extended error
information, call
GetLastError.</returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError =
true)]
[return:
MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr handle);
}
}