The LogonUser API

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.

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

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 類別,一個怪怪的範例與程式

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」認證型態。

如何取得 Win2000 AD 內使用者的相關資訊?

Delphi.ktop討論區 – 如何取得 Win2000 AD 內使用者的相關資訊?

在站上查到「使用Delphi讀取NT或2000的帳號及密碼做認證」的方法後,覺得這個功能超好用的,不用自已管理帳號密碼,真好 ^_^
但是、接下來就是想要從 NT網域伺服器 or AD 裡取得User的相關資料,例如:使用者的姓名、部門、說明…. 等等的欄位資訊.
是否有高手能分享心得 or 函式 ?
先謝謝囉 ~

function
NetUserGetInfo(ServerName:PWideChar;UserName:PWideChar;Level:DWORD;var
Buf:Pointer):Longint;stdcall;external ‘netapi32.dll’ Name
‘NetUserGetInfo’;

function NetApiBufferFree(Buff: Pointer):Integer;stdcall;external
‘netapi32.dll’ Name ‘NetApiBufferFree’;

function GetUserInfo(Server, User: String): String;

var
    UserInfo : PUSER_INFO_3;
    lpwUser : Array[0..255] Of
WideChar;
    lpwSrv : Array[0..255] Of WideChar;

begin
    StringToWideChar(Server, lpwSrv, SizeOf(lpwSrv));
    StringToWideChar(User,
lpwUser, SizeOf(lpwUser));

    NetUserGetInfo(lpwSrv,lpwUser,2,Pointer(UserInfo));

    Result := UserInfo.usri3_comment;

    NetApiBufferFree(UserInfo);

end;

使用者名稱密碼驗證程式

使用者名稱密碼驗證程式

使用者名稱密碼驗證程式

這個範例會示範如何實作自訂的 UserNamePassword 驗證程式。當內建 UserNamePassword 驗證模式都不符合應用程式需求時,這個驗證程式就很有用;例如,當使用者名稱/密碼組儲存在某些外部存放區時,例如資料庫中。這個範例示範的服務具有可檢查兩組特定使用者名稱/密碼組的自訂驗證程式。用戶端會使用這些使用者名稱/密碼組來向服務驗證。

Linux Creating or Adding New Network Alias To a Network Card (NIC)

Linux Creating or Adding New Network Alias To a Network Card (NIC)

Q. I would like to create alias for my network card (NIC). How do I setup 2 IP address on One NIC? How do I add alias under Centos / Fedora / Debian / Ubuntu Linux?

A. Linux allows you to add additional network address using alias feature. Please note that all additional network IP address must be in same subnet. For example if your eth0 using 192.168.1.5 IP address then alias must be setup using 192.168.1.0/24 subnet.

使用Spring.Net輔助切層的專案架構

[修練營ASP.NET]使用Spring.Net輔助切層的專案架構 – In 91- 點部落

[修練營ASP.NET]使用Spring.Net輔助切層的專案架構
前言

之前Danny叔叔已經發過一篇快速使用Spring.Net的Adotemplate了,詳情請見:Spring.DataQuickStart
不過這篇只把Data Access Layer跟網頁分開,使用了OR-mapping讓查詢到的資料,以object的方式回傳。

最近點部落上有不少篇很好的切層概念的文章,
例如:

1.

邁向架構師的暖身運動(5):系統開發的分層概念
2.

[修練營ASP.NET]淺談多層式架構 (Multi Tiers)
3.

還有小的一篇寫的很亂的:[工作心得]傳統程式架構到3-Layer架構的心路歷程,架構圖的部分則可以參考:[專案心得]After Action Review

切層,是一個專案考量彈性、可維護性、可擴充性等特點,在設計上無可避免的架構。
然而切層的implement方式也有相當多,
最常見的範例就是MS PetShop:http://msdn.microsoft.com/en-us/library/aa479070.aspx
下載網址:http://download.microsoft.com/download/8/0/1/801ff297-aea6-46b9-8e11-810df5df1032/Microsoft%20.NET%20Pet%20Shop%204.0.msi

然而,在Java的世界裡,Spring這個framework已經存在許久,相關的技術也相當成熟,

System.Web.Mail 太陽春、System.Net.Mail 有問題

The Will Will Web – All posts tagged ‘utf-8’

用 .NET 發信很簡單,但是要發出一封「完美的郵件」卻困難重重!我為了發一封完美的 E-Mail 遭遇到好多問題,但嘗試了很久還是無法達到 100% 的完美程度。

主要的問題整理如下:

使用 System.Web.Mail 命名空間發信的問題 ( .NET 1.0 )

*
骨子裡是使用 CDO 元件 ( Microsoft CDO for Windows 2000 ) ( CDONTS ),包裝的功能陽春到不行
*
無法將郵件的附件檔案設定為 Inline Attachment

使用 System.Net.Mail 命名空間發信的問題 ( .NET 2.0 )

*
傳送 Big5 編碼的郵件,有些中文字在 Outlook 裡會變成問號 (例如:奇, 寶)

註1:因為 System.Net.Mail 在設定 Envelop Header 時只能使用的 Quoted-Printable 編碼,如果可以選擇 Base64 問題就會迎刃而解!可惜到 .NET 3.5 還是沒有將這問題解決!

註2:微軟是建議使用 System.Net.Mail 來發信,但若真的要使用就比需要強迫使用 UTF-8 來發送郵件才不會出現問號。

其實 System.Net.Mail 寫得很好,但是這一點點小問題真的讓我很頭痛,因為有很多舊版的 WebMail 系統與一些舊版的收信軟體至今還是不支援 Unicode 的郵件閱讀,所以為了發出郵件的相容性達到最高(讓所有的人都能夠正確開啟郵件),還是有必要將郵件以 Big5 編碼的方式發送,否則總是有一些人看不到 E-Mail 或者是必須手動調整 Browser 的字集才看的到。

如果你想試看看用 System.Net.Mail 發信時如何發生錯誤,可以試試以下的程式碼,請建立一個 Console Pogram 就可以測試了:

The Will Will Web 記載著 Will 在網路世界的學習心得與技術分享 ASP.NET 如何設定強制下載檔案並正確處理中文檔名的問題

The Will Will Web – All posts tagged ‘utf-8’

我想一般人的作法都是透過設定 HTTP 回應 Content-Disposition 標頭(Header)的方式告知用戶端(Browser)強制下載檔案的,例如:

string fileName = “ExportData.csv";

string strContentDisposition = String.Format(“{0}; filename=\"{1}\"", “attachment", fileName);

Response.AddHeader(“Content-Disposition", strContentDisposition);

透過上述程式碼,就可以讓 Browser 強制下載此頁的內容,也就是該頁的內容(可能是文件或二進位檔案)不會直接在瀏覽器中開啟或下載後直接開啟相關程式(如:Office)。

其中 Content-Disposition 標頭的第一組參數是 attachment,代表此頁唯一個「附件檔」,如果你將 attchment 改成 inline 的話,就代表這是一個內嵌與其他網頁內檔案(如:圖檔、CSS、JavaScript、Flash、…),而這也是「預設」的設定,所以也就等於不加上 Content-Disposition 標頭的情況。

而 Content-Disposition 標頭的第二組參數是 filename,也就是你可以指定下載檔案時預設的儲存檔名,在此範例中的下載檔名是 ExportData.csv (如下圖示)