ASP.NET 安全架構以 Principal (主體) 與 Identity (身分) 為核心。Principal = Identity + Roles + Custom Data。本文深入解析 IPrincipal、IIdentity 介面、WindowsPrincipal/FormsIdentity 實作、HttpContext.Current.User 存取方式與角色授權檢查。
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string Name { get; }
string AuthenticationType { get; }
bool IsAuthenticated { get; }
}
| 驗證模式 | Identity 類別 | Principal 類別 | 備註 |
|---|---|---|---|
| Windows 驗證 | WindowsIdentity | WindowsPrincipal | 角色對應 Windows 群組 |
| Forms 驗證 | FormsIdentity | GenericPrincipal / 自訂 Principal | Ticket 儲存於 Cookie |
| Passport | PassportIdentity | PassportPrincipal | 已淘汰 |
| 自訂 | 實作 IIdentity | 實作 IPrincipal | 彈性最高 |
// 取得目前使用者 Principal
IPrincipal user = HttpContext.Current.User;
// 檢查是否驗證
if (user.Identity.IsAuthenticated)
{
lblUser.Text = $"{user.Identity.Name} 已登入";
}
// 角色授權檢查
if (user.IsInRole("Admin"))
{
// 顯示管理功能
}
// 取得 FormsIdentity 具體 Ticket
if (user.Identity is FormsIdentity fid)
{
FormsAuthenticationTicket ticket = fid.Ticket;
string userData = ticket.UserData; // 自訂資料 (如 UserId、權限 JSON)
}
public class CustomPrincipal : IPrincipal
{
public IIdentity Identity { get; }
public string[] Roles { get; }
public int UserId { get; }
public string[] Permissions { get; }
public CustomPrincipal(FormsIdentity identity, string[] roles, int userId, string[] permissions)
{
Identity = identity;
Roles = roles;
UserId = userId;
Permissions = permissions;
}
public bool IsInRole(string role) => Array.Exists(Roles, r => r.Equals(role, StringComparison.OrdinalIgnoreCase));
public bool HasPermission(string perm) => Array.Exists(Permissions, p => p.Equals(perm, StringComparison.OrdinalIgnoreCase));
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.User?.Identity is FormsIdentity fid)
{
// 從 Ticket.UserData 或資料庫讀取角色/權限
string[] roles = GetRoles(fid.Ticket.Name);
string[] perms = GetPermissions(fid.Ticket.Name);
int userId = GetUserId(fid.Ticket.Name);
HttpContext.Current.User = new CustomPrincipal(fid, roles, userId, perms);
Thread.CurrentPrincipal = HttpContext.Current.User; // 同步執行緒主體
}
}
HttpContext.Current.User 是每個請求的 Principal,請求結束即銷毀。user.IsInRole,避免直接比對 user.Identity.Name。