Archive for 五月, 2010

用其他身份執行程式

星期四, 五月 27th, 2010

Delphi.ktop討論區 – 用其他身份執行程式

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

const
LOGON_WITH_PROFILE = 1;
LOGON_NETCREDENTIALS_ONLY = 2;

function CreateProcessWithLogon(
lpUsername: PWChar;
lpDomain: PWChar;
lpPassword: PWChar;
dwLogonFlags: DWORD;
lpApplicationName: PWChar;
lpCommandLine: PWChar;
dwCreationFlags: DWORD;
lpEnvironment: Pointer;
lpCurrentDirectory: PWChar;
const lpStartupInfo: TStartupInfo;
var lpProcessInfo: TProcessInformation
): BOOL; stdcall;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function CreateProcessWithLogon; external advapi32 name ‘CreateProcessWithLogonW’;

procedure TForm1.Button1Click(Sender: TObject);
var
wUsername, wDomain, wPassword, wApplicationName: WideString;
pwUsername, pwDomain, pwPassword, pwApplicationName: PWideChar;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
wUsername := ‘administrator’;
wDomain := 』;
wPassword := ‘123456′;
wApplicationName := ‘cmd.exe’;
pwUsername := Addr(wUsername[1]);
pwDomain := Addr(wDomain[1]);
pwPassword := Addr(wPassword[1]);
pwApplicationName := Addr(wApplicationName[1]);

FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
StartupInfo.cb := SizeOf(TStartupInfo);
if not CreateProcessWithLogon(pwUsername,pwDomain,pwPassword,LOGON_WITH_PROFILE,
pwApplicationName,nil,CREATE_DEFAULT_ERROR_MODE,
nil,nil,StartupInfo,ProcessInfo) then
RaiseLastOSError;
end;

end.

可帶入其他使用者的Profile,使用上比LogonUser、CreateProcessAsUser簡單,省去設定SE_TCB_NAME privilege

如何從動態伺服器網頁 (Active Server Page) 模擬使用者

星期四, 五月 27th, 2010

如何從動態伺服器網頁 (Active Server Page) 模擬使用者

本文將告訴您動態伺服器網頁 (ASP) 的模擬和安全性內容。文中內容會提供可從 ASP 網頁產生實體的 Microsoft Visual Basic ActiveX 動態連結程式庫 (DLL) 程式碼範例,以便模擬使用者並變更目前執行緒的安全性內容。

根據預設,ASP 會在模擬使用者的安全性內容中執行。Web 伺服器會在收到對 ASP 檔案的要求時使用工作執行緒,並將該執行緒的安全性內容設定為模擬使用者。Internet Information Server (IIS) 驗證方法 (匿名、基本、NT 整合等) 會決定模擬使用者為何。接著,ASP 程式碼就會在該使用者的內容中執行。

您可以在模擬使用者時,解決下列出現在應用程式中的安全性衝突:

* 使用「NT 整合」(NTLM) 安全性或是 Kerberos 來驗證,而且必須通過「具名管道」通訊協定來存取網路資源 (例如,檔案、Access 資料庫或是 SQL Server) 的應用程式。
* 從 Session_OnEnd 或 Application_OnEnd 事件來存取網路資源的應用程式。

使用處理程序的識別碼來執行 Session_OnEnd 和 Application_OnEnd 事件。如果是同處理序或「低」應用程式保護的應用程式,這個識別碼就會是 SYSTEM 使用者 ID,而處理程序就會是 Inetinfo.exe 檔案。相對於模擬,您也可以執行不同的記憶體處理程序、或是使用「高」(獨立的) 應用程式保護,並將 Microsoft Transaction Server (MTS) 套件或 COM+ 應用程式的識別碼設定為想要的使用者 ID。
* 支援多位使用者透過「Microsoft Active Directory 服務介面」(Microsoft Active Directory Services Interface,ADSI) 連線到 WinNT:// 命名空間的應用程式。

這些連線會與第一個開啟連線的使用者安全性憑證,一起存入快取。 執行模擬可以確保只有單一使用者開啟該連線;因此,該使用者的憑證就會與快取的憑證相符。

在 Reporting Services 中使用 Forms 驗證

星期四, 五月 27th, 2010

在 Reporting Services 中使用 Forms 驗證 (Microsoft SQL Server 2000 技術文件)

Microsoft Corporation

2004 年 3 月

適用於:
Microsoft®SQL Server™2000 Reporting Services

摘要:學習主要著重在 Forms 驗證的 Reporting Services 安全性擴充性能。此外,下載及部署 Reporting Services 的 Forms 驗證擴充功能範例。

(請注意:範例程式碼中的註解均為英文,此文章中所顯示的中文化註解,僅供參考)

(列印共 23 頁)

若要安裝範例程式碼,請下載 Forms 驗證範例安裝程式並在您的電腦上執行。
目錄

簡介
關於本指南
Reporting Services 平台
Forms 驗證範例
結論
其他資源
簡介

部署安全的分散式企業報表解決方案是一項深具挑戰性的過程。從報表存取、到提供重要及機密資料的資料來源,有關在您的報表環境中如何安全地驗證及授權使用者,您必須作出若干決策。而且您報表的安全性僅如在報表連鎖中最脆弱的一個連結。

您需要的安全性類型取決於您的報表環境和已有的安全性系統類型。Microsoft®Windows®驗證是保護 Microsoft®SQL Server™2000 Reporting Services 中報表的主要系統。Windows 驗證提供與其他 Microsoft 伺服器產品緊密的整合;因為 Reporting Services 是在 Windows 驗證上設計和測試的,所以在這個環境中最為安全。

在有些例子中,您可能需要擴充 Reporting Services 安全性系統來適應您企業中的自訂安全性。您可以經由豐富的 Reporting Services API 開發平台來完成這項工作。本指南會呈現在 Reporting Services 中的擴充功能概觀,以及特別是安全性擴充功能。您也可以下載並瀏覽設計來 Reporting Services 並用的 Forms 驗證擴充功能範例。然後,您應該就能夠從 Reporting Services 安全性擴充功能獲益,新增自訂安全性到您的企業報表解決方案。
關於本指南

本指南中的資訊是設計用來:

* 為您介紹 Reporting Services 安全性擴充功能。
* 識別在 Reporting Services 的何處和如何您需要自訂驗證和授權。
* 說明在 Reporting Services 中驗證和授權如何運作。
* 討論 Forms 驗證和如何實作。
* 提供您可以下載和瀏覽的 Forms 驗證範例。

須知事項

本指南並非 ASP.NET 安全性或 Forms 驗證的簡介。它並不會提供您程式設計或應用程式安全性的深入知識。做為一個企圖要實作 Reporting Services 安全性擴充功能的開發人員,您應該已經有下列其中之一或以上的深入經驗:

* Microsoft Reporting Services 功能,特別是驗證、授權和角色架構安全性。
* Microsoft .NET Framework。
* ASP.NET 和 ASP.NET 安全性。
* Forms 驗證。
* 在 .NET 語言的開發經驗。此範例目前只適用於 C#。

如果您要直接探究程式碼的話,可以向前跳到<Forms 驗證範例>一節。不過,您會發現開頭的幾節所介紹的一些您會使用到的技術以及它們如何配合在一起是很有用的。

LogonUser problem

星期四, 五月 27th, 2010

Directory Programming .NET – LogonUser problem

I hate ‘logonuser’. Hopefully the below code will help someone…

CreateProcessAsUser from System Service (VB.NET)

The following code has been tested on Windows 2003 SP2. The calling user account must have ‘Assign Primary Token’ and ‘Increase Quota’ permissions to properly execute CreateProcessAsUser; see MS KB285879.

Public Function RunProc(ByVal CMD As String, ByVal ARG As String) As String
Dim er As Int16
Dim exitCode As System.UInt32 = Convert.ToUInt32(123)

Dim saThreadAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
saThreadAttributes.nLength = Marshal.SizeOf(saThreadAttributes)

Dim impToken As System.IntPtr = IntPtr.Zero
Dim priToken As System.IntPtr = IntPtr.Zero

If LogonUser(『DomainUser』, 『Domain』, 『Passwd』, LogonType.LOGON32_LOGON_INTERACTIVE, _
LogonProvider.LOGON32_PROVIDER_DEFAULT, impToken) Then
If DuplicateTokenEx(impToken, &H2000000, Nothing, SecurityImpersonationLevel.SecurityDelegation, TOKEN_TYPE.TokenPrimary, priToken) Then

Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
Dim si As STARTUPINFO = New STARTUPINFO
si.cb = Marshal.SizeOf(si)
si.lpDesktop = IntPtr.Zero

Dim saProcessAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
saProcessAttributes.nLength = Marshal.SizeOf(saProcessAttributes)

If Not CreateProcessAsUser(priToken, CMD, CMD & 』 』 & ARG, saProcessAttributes, _
saThreadAttributes, False, 0, IntPtr.Zero, 『c:\』, si, pi) Then

er = Marshal.GetLastWin32Error
RunProc = (『err runas 』 & er)

Else
WaitForSingleObject(pi.hProcess, Infinite)
GetExitCodeProcess(pi.hProcess, exitCode)
End If
CloseHandle(priToken)
CloseHandle(impToken)
CloseHandle(pi.hProcess)
CloseHandle(pi.hThread)
End If
End If
End Function

如何從 Visual Basic 的其他使用者身分啟動處理序

星期四, 五月 27th, 2010

如何從 Visual Basic 的其他使用者身分啟動處理序

本文將告訴您如何以程式設計的方式以另一個使用者從 Microsoft Visual Basic 啟動處理序。如果要執行這項操作,您可以使用 LogonUser 和 CreateProcessAsUser Win32 API,正在執行 Microsoft Windows NT 4.0 的電腦上或您可以使用 CreateProcessWithLogonW Win32 API,正在執行 Microsoft Windows 2000 的電腦上或更新版本。無法從處理序在 LocalSystem 帳戶下呼叫 CreateProcessWithLogonW。
回此頁最上方

如何從 Visual Basic 的其他使用者身分啟動處理序

星期四, 五月 27th, 2010

如何從 Visual Basic 的其他使用者身分啟動處理序

本文將告訴您如何以程式設計的方式以另一個使用者從 Microsoft Visual Basic 啟動處理序。如果要執行這項操作,您可以使用 LogonUser 和 CreateProcessAsUser Win32 API,正在執行 Microsoft Windows NT 4.0 的電腦上或您可以使用 CreateProcessWithLogonW Win32 API,正在執行 Microsoft Windows 2000 的電腦上或更新版本。無法從處理序在 LocalSystem 帳戶下呼叫 CreateProcessWithLogonW。
回此頁最上方

LogonUser problem

星期四, 五月 27th, 2010

Directory Programming .NET – LogonUser problem

I hate ‘logonuser’. Hopefully the below code will help someone…

CreateProcessAsUser from System Service (VB.NET)

The following code has been tested on Windows 2003 SP2. The calling user account must have ‘Assign Primary Token’ and ‘Increase Quota’ permissions to properly execute CreateProcessAsUser; see MS KB285879.

Public Function RunProc(ByVal CMD As String, ByVal ARG As String) As String
Dim er As Int16
Dim exitCode As System.UInt32 = Convert.ToUInt32(123)

Dim saThreadAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
saThreadAttributes.nLength = Marshal.SizeOf(saThreadAttributes)

Dim impToken As System.IntPtr = IntPtr.Zero
Dim priToken As System.IntPtr = IntPtr.Zero

If LogonUser(『DomainUser』, 『Domain』, 『Passwd』, LogonType.LOGON32_LOGON_INTERACTIVE, _
LogonProvider.LOGON32_PROVIDER_DEFAULT, impToken) Then
If DuplicateTokenEx(impToken, &H2000000, Nothing, SecurityImpersonationLevel.SecurityDelegation, TOKEN_TYPE.TokenPrimary, priToken) Then

Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION
Dim si As STARTUPINFO = New STARTUPINFO
si.cb = Marshal.SizeOf(si)
si.lpDesktop = IntPtr.Zero

Dim saProcessAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES
saProcessAttributes.nLength = Marshal.SizeOf(saProcessAttributes)

If Not CreateProcessAsUser(priToken, CMD, CMD & 』 』 & ARG, saProcessAttributes, _
saThreadAttributes, False, 0, IntPtr.Zero, 『c:\』, si, pi) Then

er = Marshal.GetLastWin32Error
RunProc = (『err runas 』 & er)

Else
WaitForSingleObject(pi.hProcess, Infinite)
GetExitCodeProcess(pi.hProcess, exitCode)
End If
CloseHandle(priToken)
CloseHandle(impToken)
CloseHandle(pi.hProcess)
CloseHandle(pi.hThread)
End If
End If
End Function

The LogonUser API

星期四, 五月 27th, 2010

The LogonUser API: ASP Alliance

Introduction

The Windows Authentication prompt can often be an intimidating dialog for users. It asks for two or three things: username, password, and sometimes domain. Users may (and should) know their network username and password combination, but how many of them know the name of the domain their account is kept on? To make matters more complex, depending on the operating system and browser version, the domain entry box isnt shown. In this case, users need to prefix their username with DomainName\:

Another solution to this is to use a standard WebForm in conjunction with a Windows API, LogonUser. The LogonUser API is a function found in the advapi32.dll file of All Windows NT, 2000, and newer based servers and workstations.

The LogonUser API

The LogonUser function is defined in the Microsoft Platform SDK as follows:

BOOL LogonUser(
LPTSTR lpszUsername,
LPTSTR lpszDomain,
LPTSTR lpszPassword,
DWORD dwLogonType,
DWORD dwLogonProvider,
PHANDLE phToken
);

This function takes five input parameters, and has a sixth output parameter, a token. A bit more on tokens will follow this. The .Net version of the API declaration is as follows (there are multiple ways to do this, all of which are functionally equivalent):

Private Declare Auto Function LogonUser Lib 『advapi32.dll』 ( _
ByVal lpszUsername As String, _
ByVal lpszDomain As String, _
ByVal lpszPassword As String, _
ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, _
ByRef phToken As IntPtr) As Boolean

There are two input parameters which LogonUser requires that are of specific interest: dwLogonType, and dwLogonProvider. The two of these control the type of logon that is initiated, and the way the credentials are passed, respectively.

There are only a couple of logon types that really apply to this context: LOGON32_LOGON_NETWORK and LOGON32_LOGON_INTERACTIVE. If your need is solely to validate the supplied credentials, then LOGON32_LOGON_NETWORK is your best choice. It is the fastest, and does not cache the logins on the server. However, if you plan to impersonate the user whose credentials were supplied, LOGON32_LOGON_INTERACTIVE is necessary. It outputs the proper type of token for use with the WindowsIdentity.Impersonate method of the .Net Framework.

Access tokens are used to by the Windows Kernel to create processes as users, and do other security type things. There are various types of tokens which can be returned, depending on the logon type, and their specifics are beyond the scope of this article. Note, it is possible to use LOGON32_LOGON_NETWORK and use the access token to impersonate a user. Additional API calls are necessary to convert the returned token to the type used by the WindowsIdentity class.

dwLogonProvider dictates the method in which the web server will pass the users credentials to the domain. There are four possible values:

LOGON32_PROVIDER_DEFAULT
LOGON32_PROVIDER_WINNT35
LOGON32_PROVIDER_WINNT40
LOGON32_PROVIDER_WINNT50

The first of the four will use the default logon protocol for the system. By default on Windows 2000, this is NTLM, which will work with Windows NT 4.0 and newer domains. If one or more of the domain controllers youll be authenticating against is still running Windows NT 3.51, youll need to use LOGON32_PROVIDER_WINNT35. If the web server is running Windows XP or Windows Server 2003, and you have a Windows NT4 or NT351 based domain, youll need to use the appropriate provider specific to that type of domain, because the default provider is LOGON32_PROVIDER_WINNT50, which is not supported by Windows NT4.

One final parameter which has some special cases is the lpszDomain parameter. To authenticate against a domain, specify the NetBIOS name of the domain in which the account resides (this is the name selected in the dropdown of a Windows Control + Alt + Del when you login to your computer). If a . Is specified, the LogonUser API will attempt to login to the local machine (web server). The name of another workstation or member server on the network may also be specified for lpszDomain.

Code

With all that said and done, its time for some code! The download for this article contains a sample webform and the associated code in Visual Basic.Net and C#. All the code shown in the article is written in Visual Basic.Net.

The first step is to declare the necessary API call, and the constants associated with it:

Private Declare Auto Function LogonUser Lib 『advapi32.dll』 ( _
ByVal lpszUsername As String, _
ByVal lpszDomain As String, _
ByVal lpszPassword As String, _
ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, _
ByRef phToken As IntPtr) As Boolean

Const LOGON32_LOGON_INTERACTIVE As Long = 2
Const LOGON32_LOGON_NETWORK As Long = 3
Const LOGON32_PROVIDER_DEFAULT As Long = 0
Const LOGON32_PROVIDER_WINNT50 As Long = 3
Const LOGON32_PROVIDER_WINNT40 As Long = 2
Const LOGON32_PROVIDER_WINNT35 As Long = 1

Step two, actually use the API that has been defined:

Private Function ValidateLogin( _
ByVal Username As String, _
ByVal Password As String, _
ByVal Domain As String) As Boolean

Dim token As IntPtr

If LogonUser(Username, _
Domain, _
Password, _
LOGON32_LOGON_INTERACTIVE, _
LOGON32_PROVIDER_DEFAULT, token) = True Then

Return True
Else
Return False
End If
End Function

In this example, Im using interactive login, to allow for easy use of the access token which is returned (and stored in the IntPtr variable token) if the API call is successful. In this example, I havent done anything with the access token which is returned, and I will not do so at all in this article.

In Conjunction with Built-in ASP.Net Authentication

Since the point of the LogonUser code is to replace the ugly Windows Auth dialog, Windows Authentication obviously isnt the solution, in terms of choosing an authentication provider, if any.

Forms authentication, on the other hand, does the trick. The page which calls the LogonUser API is a standard web form, and hence can be used for forms authentication. In the included demo files, forms authentication is demonstrated, in conjunction with the LogonUser API. The following line of code does the forms authentication:

FormsAuthentication.RedirectFromLoginPage(Username, False)

The first parameter specifies the username of the user being logged in, accessible after this via Context.User.Identity.Name, and the second parameter specifies whether or not a persistent cookie should be saved.

Handling Errors

If the API Call returns false, use this line of code to get the Win32 error code back for debugging:

System.Runtime.InteropServices.Marshal.GetLastWin32Error()

A listing of Win32 error codes can be found online at: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes.asp

Server Setup

This section applies only if youre running a Windows 2000 server. Windows XP, and Windows Server 2003 handle this behavior automatically, so no further configuration is necessary. The ASPNET account, or whatever account your server is configured to run the ASP.Net worker process account as requires the Act as Part of the Operating System user right. This is also known by the operating system, and in error messages as SE_TCB_NAME. Configuring this right is a cinch:

1. Logon to the server as an administrator
2. Open up the machines local security policy (start>run>secpol.msc)
3. Expand Security Settings, Local Policies, User Rights Assignment
4. Double click Act as part of the operating system
5. Click Add User or Group, enter the worker process account name and click OK, and OK again

In order for this change to become effective, the web server will have to be rebooted. This setting is applied when the start dialog reads Applying Security Settings.

From the Frontline

Ive used the LogonUser API in conjunction with two web applications already. It worked well. The reason I chose the API route is because of the user base Im targeting about 650 high-school students. The computers they were going to use to login were running two different operating systems, Windows NT4, and Windows 2000. The LogonUser API guaranteed me an interface which was conformant with the look of the rest of our homepage, and the ability to upgrade to Windows 2000 without changing a line of code.

I learnt the hard way that LOGON32_LOGON_INTERACTIVE is definitely not the provider to use when servicing a high volume of simultaneous login events. The first time I used the LogonUser API in a production app, I had about six-hundred users login over a thirty minute period. For reasons unbeknownst to me, the web server would reject valid credentials from time to time. It was as though the API call never executed because nothing was returned. Moral of this story, use LOGON32_LOGON_NETWORK for high load scenarios.

For my production environment, Ive encapsulated the LogonUser API call, along with several other related API calls for easy use from any web or windows application.

In Summary

For all the details of how to work with the LogonUser API call, its actually pretty simple to use. A few things to consider:

When deciding which logon provider to use, you must be sure that all of the domain controllers on the network support the protocol youre using. This means that if all but one of the domain controllers in your network is running Windows 2000, and this lone NT4 domain controller is located halfway across the globe, you still need to use the NT40 logon provider. This is because your web server could theoretically contact the NT4 domain controller, and fail to communicate the given credentials.

If you have no plans to impersonate the logged in user, use the LOGON32_LOGON_NETWORK login type. It is faster, and consumes less network resources.

If you have one account domain, I’d recommend that you store it in the appSettings area of your web.config file. That way, if your network admins ever rename the domain, you wont have to recompile the application. Obviously, if there are multiple account domains, your users or your application will have to decide which one to query.

模擬由指定使用者語彙基元所表示的使用者。

星期四, 五月 27th, 2010

WindowsIdentity.Impersonate 方法 (IntPtr) (System.Security.Principal)

‘ This sample demonstrates the use of the WindowsIdentity class to impersonate a user. ‘ IMPORTANT NOTES: ‘ This sample can be run only on Windows XP. The default Windows 2000 security policy ‘ prevents this sample from executing properly, and changing the policy to allow ‘ proper execution presents a security risk. ‘ This sample requests the user to enter a password on the console screen. ‘ Because the console window does not support methods allowing the password to be masked, ‘ it will be visible to anyone viewing the screen. ‘ The sample is intended to be executed in a .NET Framework 1.1 environment. To execute ‘ this code in a 1.0 environment you will need to use a duplicate token in the call to the ‘ WindowsIdentity constructor. See KB article Q319615 for more information. Imports System Imports System.Runtime.InteropServices Imports System.Security.Principal Imports System.Security.Permissions Imports Microsoft.VisualBasic Module Module1 Public Class ImpersonationDemo Private Declare Auto Function LogonUser Lib 『advapi32.dll』 (ByVal lpszUsername As [String], _ ByVal lpszDomain As [String], ByVal lpszPassword As [String], _ ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, _ ByRef phToken As IntPtr) As Boolean _ Public Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _ ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _ ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer End Function Public Declare Auto Function CloseHandle Lib 『kernel32.dll』 (ByVal handle As IntPtr) As Boolean Public Declare Auto Function DuplicateToken Lib 『advapi32.dll』 (ByVal ExistingTokenHandle As IntPtr, _ ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _ ByRef DuplicateTokenHandle As IntPtr) As Boolean ‘ Test harness. ‘ If you incorporate this code into a DLL, be sure to demand FullTrust. _ Public Overloads Shared Sub Main(ByVal args() As String) Dim tokenHandle As New IntPtr(0) Dim dupeTokenHandle As New IntPtr(0) Try Dim userName, domainName As String ‘ Get the user token for the specified user, domain, and password using the ‘ unmanaged LogonUser method. ‘ The local machine name can be used for the domain name to impersonate a user on this machine. Console.Write(『Enter the name of a domain on which to log on: 『) domainName = Console.ReadLine() Console.Write(『Enter the login of a user on {0} that you wish to impersonate: 『, domainName) userName = Console.ReadLine() Console.Write(『Enter the password for {0}: 『, userName) Const LOGON32_PROVIDER_DEFAULT As Integer = 0 ‘This parameter causes LogonUser to create a primary token. Const LOGON32_LOGON_INTERACTIVE As Integer = 2 tokenHandle = IntPtr.Zero ‘ Call LogonUser to obtain a handle to an access token. Dim returnValue As Boolean = LogonUser(userName, domainName, Console.ReadLine(), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle) Console.WriteLine(『LogonUser called.』) If False = returnValue Then Dim ret As Integer = Marshal.GetLastWin32Error() Console.WriteLine(『LogonUser failed with error code : {0}』, ret) Throw New System.ComponentModel.Win32Exception(ret) Return End If Dim success As String If returnValue Then success = 『Yes』 Else success = 『No』 Console.WriteLine((『Did LogonUser succeed? 』 + success)) Console.WriteLine((『Value of Windows NT token: 』 + tokenHandle.ToString())) ‘ Check the identity. Console.WriteLine((『Before impersonation: 』 + WindowsIdentity.GetCurrent().Name)) ‘ Use the token handle returned by LogonUser. Dim newId As New WindowsIdentity(tokenHandle) Dim impersonatedUser As WindowsImpersonationContext = newId.Impersonate() ‘ Check the identity. Console.WriteLine((『After impersonation: 』 + WindowsIdentity.GetCurrent().Name)) ‘ Stop impersonating the user. impersonatedUser.Undo() ‘ Check the identity. Console.WriteLine((『After Undo: 』 + WindowsIdentity.GetCurrent().Name)) ‘ Free the tokens. If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then CloseHandle(tokenHandle) End If Catch ex As Exception Console.WriteLine((『Exception occurred. 』 + ex.Message)) End Try End Sub ‘Main End Class ‘Class1 End Module

ASP.NET 透過AD進行驗證 #3 –WindowsIdentity 類別,一個怪怪的範例與程式

星期四, 五月 27th, 2010

ASP.NET透過AD進行驗證 #3 –WindowsIdentity 類別,一個怪怪的範例與程式 – MIS2000 Lab.的 ASP.NET專題實務/教學與分享- 點部落

在 System.Security.Principal命名空間(NameSapce)底下,

有一個 WindowsIdentity 類別,跟「Windows使用者」相關的。

官方文件在此:http://msdn.microsoft.com/zh-tw/library/system.security.principal.windowsidentity.aspx

裡面這個範例看得我一頭霧水。(這是什麼翻譯啊?快點回火星去吧!地球是很危險~低!)

範例說明:

下列範例顯示 WindowsIdentity 類別中成員的用法。如需顯示如何透過呼叫 Unmanaged Win32 LogonUser 函式取得 Windows 帳戶語彙基元 (Token),然後使用該語彙基元模擬其他使用者的範例,請參閱 WindowsImpersonationContext 類別。

不如直接運作一次 直接看結果,還比較清楚。

下圖是執行結果(看完執行結果,再來對照程式碼。比較容易懂)。

程式是從微軟官方文件那邊來的,小改了幾個字。如下:
001 Imports …System.Security.Principal
002
003
004 Partial Class NTAccount
005 Inherits System.Web.UI.Page
006
007 ‘===============================================
008 ‘== 下列範例顯示 WindowsIdentity 類別中,目前這位成員的用法。==
009 ‘===============================================
010 ‘
011 ‘==參考網址 http://msdn.microsoft.com/zh-tw/library/system.security.principal.windowsidentity.aspx
012
013 Protected Sub Page_Load() Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
014 ‘ Retrieve the [Windows account token] for the current user.
015 Dim logonToken As IntPtr = WindowsIdentity.GetCurrent().Token
016
017 ‘ Constructor implementations. 執行下面四個 Function
018 IntPtrConstructor(logonToken)
019 IntPtrStringConstructor(logonToken)
020 IntPtrStringTypeConstructor(logonToken)
021 IntPrtStringTypeBoolConstructor(logonToken)
022
023 ‘ Property implementations.
024 UseProperties(logonToken) ‘–UseProperties()是下面的Function
025
026 ‘ Method implementations.
027 GetAnonymousUser() ‘–GetAnonymousUser()是下面的Function
028 ImpersonateIdentity(logonToken) ‘–ImpersonateIdentity()是下面的Function
029
030 ‘ Align interface and conclude application.
031 Response.Write(『


程式完成。This sample completed ……successfully

『)
032 End Sub
033
034 ‘ Create a WindowsIdentity object for the user represented by the
035 ‘ specified Windows account token.
036 Private Sub IntPtrConstructor() Sub IntPtrConstructor(ByVal logonToken As IntPtr)
037 ‘ Construct a WindowsIdentity object using the input account token.
038 ‘重點!!一個參數
039 Dim windowsIdentity As New WindowsIdentity(logonToken)
040
041 Response.Write(『Created a Windows identity object named ( IntPtrConstructor() )– 』 + windowsIdentity.Name + 『.
『)
042 End Sub
043
044 ‘ Create a WindowsIdentity object for the user represented by the
045 ‘ [specified account token] and [authentication type].
046 Private Sub IntPtrStringConstructor() Sub IntPtrStringConstructor(ByVal logonToken As IntPtr)
047 ‘ Construct a WindowsIdentity object using the input account token
048 ‘ and the specified authentication type.
049 Dim authenticationType = 『WindowsAuthentication』
050
051 ‘重點!!兩個參數
052 Dim windowsIdentity As New WindowsIdentity(logonToken, authenticationType)
053
054 Response.Write(『Created a Windows identity object named ( IntPtrStringConstructor() )– 』 + windowsIdentity.Name + 『.
『)
055 End Sub
056
057 ‘ Create a WindowsIdentity object for the user represented by the
058 ‘ specified account token, authentication type, and Windows account type.
059 Private Sub IntPtrStringTypeConstructor() Sub IntPtrStringTypeConstructor(ByVal logonToken As IntPtr)
060 ‘ Construct a WindowsIdentity object using the input account token,
061 ‘ and the specified authentication type and Windows account type.
062 Dim authenticationType As String = 『WindowsAuthentication』
063 Dim guestAccount As WindowsAccountType = WindowsAccountType.Guest
064
065 ‘重點!!三個參數
066 Dim windowsIdentity As _
067 New WindowsIdentity(logonToken, authenticationType, guestAccount)
068
069 Response.Write(『Created a Windows identity object named ( IntPtrStringTypeConstructor() )–』 + windowsIdentity.Name + 『.
『)
070 End Sub
071
072 ‘ Create a WindowsIdentity object for the user represented by the
073 ‘ specified account token, authentication type, Windows account type,
074 ‘ and Boolean authentication flag.
075 Private Sub IntPrtStringTypeBoolConstructor() Sub IntPrtStringTypeBoolConstructor(ByVal logonToken As IntPtr)
076 ‘ Construct a WindowsIdentity object using the input account token,
077 ‘ and the specified authentication type, Windows account type, and
078 ‘ authentication flag.
079 Dim authenticationType As String = 『WindowsAuthentication』
080 Dim guestAccount As WindowsAccountType = WindowsAccountType.Guest
081 Dim isAuthenticated As Boolean = True
082
083 ‘重點!!四個參數
084 Dim windowsIdentity As _
085 New WindowsIdentity(logonToken, authenticationType, guestAccount, isAuthenticated)
086
087 Response.Write(『Created a Windows identity object named ( IntPrtStringTypeBoolConstructor() )–』 + windowsIdentity.Name + 『.
『)
088 End Sub
089
090 ‘ Access the properties of a WindowsIdentity object.
091 Private Sub UseProperties() Sub UseProperties(ByVal logonToken As IntPtr)
092 Dim windowsIdentity As New WindowsIdentity(logonToken) ‘重點!!一個參數
093 Dim propertyDescription As String = 『
The Windows identity named — 『
094
095 ‘ Retrieve the Windows logon name from the Windows identity object.
096 propertyDescription += 『』 + windowsIdentity.Name + 『
097
098 ‘————————————————————–(start)–
099 ‘ Verify that the user account is not considered to be an Anonymous
100 ‘ account by the system.
101 If Not windowsIdentity.IsAnonymous Then
102 propertyDescription += 』 is not(非) an Anonymous(匿名) account

103 End If
104
105 ‘ Verify that the user account has been authenticated by Windows.
106 If (windowsIdentity.IsAuthenticated) Then
107 propertyDescription += 『, is authenticated(已認證)

108 End If
109
110 ‘ Verify that the user account is considered to be a System account by
111 ‘ the system.
112 If (windowsIdentity.IsSystem) Then
113 propertyDescription += 『, is a System account(系統帳號)

114 End If
115
116 ‘ Verify that the user account is considered to be a Guest account by
117 ‘ the system.
118 If (windowsIdentity.IsGuest) Then
119 propertyDescription += 『, is a Guest account(Guest客人帳戶)

120 End If
121 ‘————————————————————–(end)–
122
123 Dim authenticationType As String = windowsIdentity.AuthenticationType
124
125 ‘ Append the authenication type to the output message.
126 If (Not authenticationType Is Nothing) Then
127 propertyDescription += (』 and uses 』 + authenticationType + 『 authentication type.
『)
128 End If
129
130 Response.Write(propertyDescription)
131
132 ‘ Display the SID for the owner.
133 Response.Write(『

The SID for the owner is : 『)
134 Dim si As SecurityIdentifier = windowsIdentity.Owner
135 Response.Write(『』 + si.ToString() + 『
『)
136
137 ‘————————————————————–(start)
138 ‘ Display the SIDs for the groups the current user belongs to.
139 Response.Write(『

Display the SIDs for the groups the current user belongs to. 目前這名使用者隸屬於哪些群組?
『)
140
141 Dim irc As IdentityReferenceCollection = windowsIdentity.Groups
142 Dim ir As IdentityReference
143
144 For Each ir In irc
145 Response.Write(『』 + ir.Value + 『
『)
146 Next
147 ‘————————————————————–(end)
148
149 Dim token As TokenImpersonationLevel = windowsIdentity.ImpersonationLevel
150 Response.Write(『
The impersonation(模擬) level for the current user is : 』 + token.ToString() + 『
『)
151 End Sub
152
153
154
155 ‘—————————————————————————————————————————–
156
157 ‘ Get the WindowsIdentity object for an Anonymous user.
158 Private Sub GetAnonymousUser() Sub GetAnonymousUser()
159 ‘ Retrieve a WindowsIdentity object that represents an anonymous
160 ‘ Windows user.
161 Dim windowsIdentity As WindowsIdentity = windowsIdentity.GetAnonymous()
162 End Sub
163
164
165 ‘ Impersonate a Windows identity.
166 Private Sub ImpersonateIdentity() Sub ImpersonateIdentity(ByVal logonToken As IntPtr)
167 ‘ Retrieve the Windows identity using the specified token.
168 Dim windowsIdentity As New WindowsIdentity(logonToken)
169
170 ‘ Create a WindowsImpersonationContext object by impersonating the Windows identity.
171 Dim impersonationContext As WindowsImpersonationContext = windowsIdentity.Impersonate()
172
173 Response.Write(『Name of the identity after impersonation(模擬): 』 + windowsIdentity.GetCurrent().Name + 『.
『)
174
175 ‘ Stop impersonating the user.
176 impersonationContext.Undo()
177 ‘ Check the identity.
178 Response.Write(『Name of the identity after performing an Undo on the impersonation(模擬): 』 + windowsIdentity.GetCurrent().Name + 『.』)
179 End Sub
180
181 End Class

認證型態,在單機裡面,會是NTLM。(如上圖,我的電腦是Windows Vista)

如果你的電腦有加入AD網域,則會是「Kerberos」認證型態。