[ASP.Net] 如何部屬當Windows 整合驗證失敗後自動導向ASP.Net Form驗證

在MSND網站上有一篇文章討論到如何實作當使用者遇到Windows 整合驗證失敗後自動導向ASP.Net Form驗證 , 這邊我們來實作這篇文章. 這邊您可以選擇當使用者被導向到ASP.Net Form驗證時,是遇到AD驗證或是您的資料庫驗證.

在MSND網站上有一篇文章討論到如何實作當使用者遇到Windows 整合驗證失敗後自動導向ASP.Net Form驗證 , 這邊我們來實作這篇文章. 這邊您可以選擇當使用者被導向到ASP.Net Form驗證時,是遇到AD驗證或是您的資料庫驗證.

相關參考網站資訊:

Mixing Forms and Windows Security in ASP.NET

http://msdn.microsoft.com/en-us/library/ms972958.aspx

 

在這個專案需要開發到的檔案為WinLogin.aspx , WebLogin.aspx , Redirect401.htm , Web.config ,global.asax. 以下來說明這些檔案的相關資訊:

1. Forms Authentication(表單驗證)

Each ASP.NET application can only have one authentication type, so you need to pick just one. Windows authentication only provides the username, whether it be the ASP.NET process user, or the actual client user if Microsoft® Internet Information Services (IIS) is configured to disable anonymous access—nothing more. Once you accept this, it should be clear that only Forms authentication is customizable.

So let's proceed by setting Forms authentication in our application's web.config file. This is also a good time to point out that you need to make sure your ASP.NET application is in fact an IIS application also, since this is required for all authentication types. You also need to specify your authorization in web.config, which is to deny anonymous users. The authentication forms sub-tag defines several attributes, one of which is the loginUrl, which is where ASP.NET will automatically redirect all un-authorized users on any access.

每個ASP.Net應用程式只能使用一種登入的驗證方式.因此在這個議題上我們必須利用流程來解決Windows 驗證與ASP.Net Form驗證的整合. 整個架構流程如下:  

當使用者登入網站並且提出瀏覽網頁需求的時候.

1. 當使用者登入網站時,儲存ReturnUrl資訊到Cookie裡.

2. 在Web.config裡設定將網頁導向WinLogin.aspx頁面.

3. 接著使用者會遇到IIS Windows 整合驗證的挑戰與回應視窗.

4. 若IIS Windows 整合驗證成功則由 WinLogin.aspx此網頁來導向使用者到原來的要求網頁.

5. 若IIS 整合驗證失敗則導向Redirect401.htm網頁.

6. 客製Redirect401.htm此網頁導向WebLogin.aspx,讓使用者轉向為Form驗證.

7. User在這個網頁上做登入認證成功之後再導向使用者到原本的需求頁面.

clip_image001

2. IIS Windows Security( 設定此應用程式網站預設由Windows Form驗證 )

The next thing you need to do is to handle the Windows Integrated security at WinLogin.aspx. There's actually several pieces to this, and separating them out will help implement it. This process consists of denying anonymous users, getting the client's Windows credentials, capturing the client's Windows username, and then plugging this into Forms authentication. Please note that we will deal with the case where Integrated Windows security fails later. Also note there is no html in WinLogin.aspx; it's just an Integrated Windows security test.

Let's proceed by denying anonymous users and getting the client's Windows credentials. This description of the problem should make it clear that IIS is the solution you need here, since it already has both of these capabilities built into it—you just need to use them. Using the IIS Manager, right-click the WinLogin.aspx file, click Properties, and then go to the File Security tab to edit the authentication and access control for this single file. Then simply un-check Enable anonymous access and check Integrated Windows authentication.

這邊我們要在IIS管理介面中設定WinLogin.aspx網頁,這邊要取消[匿名存取]。並且勾起[整合式Windows驗證]。流程中一開始我們要讓使用者先遇上Windows 整合驗證。

3.1 到IIS管理中心的MixedSecurity站台中到到WinLogin.aspx頁面設定其為Windows 整合頁面

clip_image002

clip_image003

Unfortunately, this does not automatically give you the username; you need a little more. The solution can be found with a page trace, or by using a decompiler on the OnEnter method of the WindowsAuthenticationModule. The username is a server variable named LOGON_USER. All you need to do is capture the username using Request.ServerVariables["LOGON_USER"], and then call FormsAuthentication.RedirectFromLoginPage to plug into Forms authentication. This single method both sets the authentication cookie and redirects to the original page.

當使用者通過Windows 整合驗證的時候,您必須再自行取得您的登入名稱,利用Request.ServerVariables["LOGON_USER"]來取得使用者登入名稱。然後再呼叫FormsAuthentication.RedirectFromLoginPage 方法來重導網頁到原本的需求頁面。並且您可以在這個方法上儲存您的authentication cookie。如果使用者在這個階段驗證失敗,則網頁會被導向Weblogin.aspx網頁來繼續Form驗證的動作。

 

clip_image004

我們在Web.COnfig檔案裏面設定這個Asp.net程式驗證typeForms,登入的頁面為 WinLogin.aspx。接著我們設定WebLogin.aspx頁面可以接受匿名驗證的存取。這部分是讓Windows 整合驗證失敗的時候,使用者可以被導向到WebLogin驗證的頁面。

clip_image005

這部分的Web.config設定相關資訊可以參考下面網站:

location 項目 (ASP.NET 設定結構描述)

http://msdn.microsoft.com/zh-tw/library/b6x6shw7.aspx

clip_image006

3. IIS Custom 401 Errors (Windows整合驗證失敗後將網頁導向到Form驗證)

That's all that you would need to do if you only wanted to use Integrated Windows security. But you also want to handle the case where Integrated Windows security fails for some users, by somehow redirecting them to your own custom logon screen to get their user credentials. Also note that the implementation of Integrated Windows security depends on the browser, since non-Internet Explorer browsers present the user with a logon dialog that they can cancel to fail. So you need to understand what happens when the Integrated Windows security check fails.

What does happen when Integrated Windows security fails? The user gets a 401 error. ASP.NET has a built-in feature to capture and redirect most errors in the web.config file, but unfortunately 401 and 403 errors are the exception and must be handled in other ways. Once again, the description of the problem should make it clear that IIS is the solution. While you can trigger authentication by sending a 401 status code to avoid configuring IIS, I don't know of any way to avoid getting involved with IIS to actually handle a 401 error.

Using the IIS Manager, right-click the WinLogin.aspx file, click Properties, and then go to the Custom Errors tab to Edit the various 401 errors and assign a custom redirection. Unfortunately, this redirection must be a static file—it will not process an ASP.NET page. My solution is to redirect to a static Redirect401.htm file, with the full physical path, which contains javascript, or a meta-tag, to redirect to the real ASP.NET logon form, named WebLogin.aspx. Note that you lose the original ReturnUrl in these redirections, since the IIS error redirection required a static html file with nothing dynamic, so you will have to handle this later.

Windows整合驗證失敗後,我們要將網頁導向到Form驗證去。因為錯誤的回應頁面我們只能重IIS上來指向,無法重程式裡面來客製化。因此我們這邊客製一個網頁為Redirect401.htm來重新導向錯誤頁面。錯誤的回應頁面在使用者經由Windows Form驗證失敗後,這邊我們將IIS401錯誤頁面導向到我們客製化的頁面上。然後我們利用javascript語法來重新導向錯誤頁面到web form 認證頁面 。這邊我們將其導向到 [WebLogin.aspx] 頁面。

 

clip_image007

clip_image008

clip_image009

clip_image010

4. Forms Custom Logon (客製化WebLogin.aspx網頁)

The next step is to create the usual Forms authentication logon screen, named WebLogin.aspx. The UI should at least contain textboxes for the user to enter the username and password, as well as a submit button to log on, but you may want to add other logon features as well. You'll also need to add your own authentication code in the logon button's event handler, since I've kept it very simple by just testing if the username and password are identical. You may also want to add support for roles, either your own custom roles or Windows groups.

At this point you now have an authenticated user, along with their username, to work with. You could just call FormsAuthentication.RedirectFromLoginPage to once again plug into the Forms authentication, but that doesn't quite work since we lost the original ReturnUrl. So you have to separately set the authentication cookie, using FormsAuthentication.SetAuthCookie, and then manually redirect to the original ReturnUrl, which will be discussed very soon. This at first sounds like it should work, but you end up just looping again to WinLogin.aspx.

So why don't you get to your WebLogin.aspx page? You don't have the proper permissions yet. You started by setting up Forms authentication and set authorization to deny anonymous users, which is smart enough to allow anonymous users to access the loginUrl, but that's WinLogin.aspx. So you need to also explicitly set authorization for WebLogin.aspx to allow anonymous users, which is easily done using a location section in the web.config file, with path WebLogin.aspx. And that's it—you have now have successfully combined Forms and Windows security in ASP.NET.

接著我們建立一個網頁,這是一個Form驗證的網頁。當使用者的Windows 整合驗證失敗後會被Redirect401.htm導到這一個網頁來進行ASP.NetForm驗證。我們會在這個網頁撰寫簡單的程式來模擬Form驗證的成功,只要您在網頁的UserName輸入的值等於您在Password輸入的值,我們就讓Windows Form驗證成立。當然這是這邊範例的部分,您可以更改程式碼來符合您的需求。例如程式向資料庫驗證使用者帳號與密碼。

clip_image011

 

 

clip_image012

 

5. Redirect Original URL (將使用者導向原本的需求頁面)

So now the only remaining problem is to track the original URL, so the redirect can work. The Forms authentication module automatically adds a ReturnUrl querystring to WinLogin.aspx, but Integrated Windows security prevents this page from ever running for non-Windows users. Then IIS forces you to redirect those users to a static html file, so the querystring is lost. You need to instead track the original URL with something more persistent, like cookies or session, although we first have to figure out how to capture that original URL to save it.

Forms authentication works through an HttpModule that intercepts and processes all requests, which then redirects un-authenticated users before the original requested page is ever loaded. This means that you need to also plug in to the request at an earlier time, like in global.asax, where there is already an AuthenticateRequest event that you can handle to capture the URL. So just check if the request is not authenticated, and then set the request's path to be the value of the ReturnUrl cookie that you will redirect back to in your WebLogin.aspx page.

That sounds right, but now you end up just looping back to WebLogin.aspx, not the original URL. Debugging at this point easily finds the problem: You are overwriting the ReturnUrl cookie when WebLogin.aspx is requested, so you just need to not change the cookie for this one case. There is also one other situation that can occur: The user can go directly to WebLogin.aspx, which will now not have a ReturnUrl cookie, so you simply need to check and handle this also. Now you finally have combined Forms and Windows security, along with the original redirect.

Form驗證的方式可以利用取得querystring使用者Request的網址,但是在Windows 整合驗證的方式因為IIS會導向您到static html網頁,因此就無法使用querystring來取得原始需求網址。因此您必須用其他的方式來保留這個網址,例如運用cookie或是session的方式。

 

 

 

 

 

6. 在ASP.Net Form驗證的部分也是針對AD來做驗證

n 範例程式中我架設的網域為Example.com,這部分您需要依照您的環境來更改您的LADP路徑。

clip_image013

n 當使用者來到ASP.Net Form驗證的頁面時 ,會遇到如下圖的登入畫面,網頁要求您輸入網域認證相關資訊。

clip_image014

clip_image015

n 若是驗證失敗,利用下方顯示出錯誤資訊。

clip_image016

詳細程式撰寫相關資訊請參考下列網站:

如何使用表單驗證及 Visual Basic .NET 通過 Active Directory 驗證

http://support.microsoft.com/kb/326340/zh-tw

clip_image017