在 2023 討論 ASP.NET WebForm,有點像大家都在聊海拉魯,你卻在研究瑪俐歐要怎麼救公主,邊緣感十足。但這個茶包讓我踩了好幾次雷,想想還是寫一篇紀念一下。

要在 ASP.NET 取得登入網站的使用者帳號,我們有不少舊程式是用 Request.LogonUserIdentity.Name 取值,運作多年相安無事,不覺得有什麼問題。但在測試台因特殊需求改用 Form 驗證(表單驗證)之後,問題一一浮現。

這裡借用之前文章的 Form 驗證程式小做修改,在頁面顯示 User.GetType().Name、Request.LogonUserIdentity.Name、User.Identity.Name 對照,進行實測驗證。

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <h3>WebForm</h3>
        <div>
            User.GetType().Name = <%= User.GetType().Name %> <br />
            Request.LogonUserIdentity.Name = <%= Request.LogonUserIdentity.Name %> <br />
            User.Identity.Name = <%= User.Identity.Name %> 
        </div>
        <a href="ShowUser.ashx">ShowUser.ashx</a> 
        <a href="Logout.aspx">Logout.aspx</a>
    </form>
</body>
</html>

先設定 Windows 整合式驗證,此時 HttpContext.Current.User 物件型別為 WindowsPrincipal,Request.LogonUserIdentity 與 User.Identity 結果相同,換言之,若 IIS 走 Windows 驗證,兩種寫法都能正確抓到使用者登入帳號:

切換到 Form 驗證,結果就不同了,User 型別變成 GenericPrincipal,但 Request.LogonUserIdentity 顯示的是 IIS AppPool 執行身分,User.Identity 傳回的才是 Form 驗證的登入帳號:

LogonUserIdentity 之所以能正確運行沒出問題,是因為原本的開發測試環境及線上環境都是使用 Windows 整合式驗證;要同時支援 Windows 驗證及 Form 驗證,請使用 User.Identity。

Experiment to illustrate the difference between User.Identity and Request.LogonUserIdentity in Windows and form authentications.


Comments

# by Huang

一開始就只學Form驗證,也只學會使用User.Identity...XD

Post a comment