ASP.NET Webform 簡易活動報名系統(7) 後台登入頁Login.aspx

by | 3 月 24, 2025 | 程式 | 0 comments

Views: 4

這篇要介紹一個重要觀念,「後台」,一般來說給普通使用者使用的會稱為前台,給管理員用的會稱為後台,而進入後台要通過一個登入頁登入到後端去。這篇文章主要教怎建立一個登入頁,這邊直接使用寫死(直接寫在程式碼內)的帳密。

網站地圖Site Map

網站地圖

網站地圖對於快速理解有哪些功能要開發相當重要,地圖中會顯示網站中各個頁面怎麼連結,以及各個頁面。

新增資料夾 Admin

先停止偵錯

停止偵錯

如果專案還在啟動運行中,請先停止偵錯

加入Admin資料夾

新增資料夾

對著專案按滑鼠右鍵專案>加入Add>新增資料夾New Folder

如果沒看到加入 > 新資料夾,代表你的專案還在偵錯當中,要先停止偵錯。

Admin

輸入Admin作為資料夾名稱

在Admin內建立Event跟Member資料夾

Admin資料夾內加入其他資料夾

然後在Admin資料夾內照同樣步驟建立兩個資料夾EventMember

Event

加入登入頁-Login.aspx

登入頁

同樣在Admin資料夾>加入>使用主版頁面的 Web Form

Login

輸入頁面名稱Login > 確定

選擇版面

選擇Site.Master作為主版頁面 > 確定

Login.aspx

登入頁Login.aspx

登入頁基本上要幾樣東西

  1. 標題 h2
  2. 帳號輸入 Lable + TextBox
  3. 密碼輸入 Lable + TextBox
  4. Submit 送出
  5. 顯示登入失敗的訊息

Login.aspx的程式碼

這邊還沒美化,元件之前都教過了,直接給程式碼

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="PartyRegister.Admin.Login" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <h2>後台管理登入</h2>
    <asp:Label runat="server" ID="lbAccount" Text="帳號"></asp:Label>
    <asp:TextBox runat="server" ID="tbAccount" Text="帳號"></asp:TextBox>
    <asp:Label runat="server" ID="lbPasswd" Text="密碼"></asp:Label>
    <asp:TextBox runat="server" ID="tbPasswd" Text="密碼" TextMode="Password"></asp:TextBox>
    <asp:Button runat="server" ID="btnSubmit" Text="登入" />
    <asp:Button runat="server" ID="btnClear" Text="清除" />
</asp:Content>

登入頁面

不過這樣有點醜,我們要處理一下畫面。

美化後登入頁面

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="PartyRegister.Admin.Login" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <style>
        .login-container {
            min-height: 80vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .card {
            width: 100%;
            max-width: 400px;
            box-shadow: 0 0 20px rgba(0,0,0,0.05);
            border-radius: 10px;
        }

        .card-header {
            border-top-left-radius: 10px;
            border-top-right-radius: 10px;
        }

        .w-45 {
            width: 48%;
        }
        input{
            max-width: 100% !important;
        }
    </style>
    <div class="login-container">
        <div class="container">
            <div class="card mx-auto">
                <div class="card-header">
                    <h2 class="h5">後台管理登入</h2>
                </div>
                <div class="card-body">
                    <div class="row">
                        <div class="col-12">
                            <asp:Label runat="server" ID="errorMsg" ForeColor="red"></asp:Label>
                        </div>
                        <div class="col-12">
                            <div class="form-group">
                                <asp:Label runat="server" ID="lbAccount" Text="帳號"></asp:Label>
                                <asp:TextBox runat="server" ID="tbAccount" Text="" placeholder="請輸入帳號" CssClass="form-control w-100"></asp:TextBox>
                            </div>
                        </div>
                        <div class="col-12">
                            <div class="form-group">
                                <asp:Label runat="server" ID="lbPasswd" Text="密碼"></asp:Label>
                                <asp:TextBox runat="server" ID="tbPasswd" Text="密碼" TextMode="Password" CssClass="form-control w-100" placeholder="請輸入密碼" AutoCompleteType="Disabled"></asp:TextBox>
                            </div>
                        </div>
                        <div class="col-12">
                            <div class="form-group mt-3 d-flex justify-content-between">
                                <asp:Button runat="server" ID="btnSubmit" Text="登入" CssClass="btn btn-primary w-45" />
                                <asp:Button runat="server" ID="btnClear" Text="清除" CssClass="btn btn-dark w-45" />
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</asp:Content>

美化頁面不是我的強項,我簡單用Card搭一下後,請chatGpt幫我調整

登入頁面

建立後端Login.aspx.cs

Login.aspx 前端兩個按鈕加入OnClick事件

  1. ID="btnSubmit" 加入 OnClick="btnSubmit_OnClick"
  2. ID="btnClear" 加入 OnClick="btnClear_OnClick"
<asp:Button runat="server" ID="btnSubmit" Text="登入" CssClass="btn btn-primary w-45" OnClick="btnSubmit_OnClick" />
<asp:Button runat="server" ID="btnClear" Text="清除" CssClass="btn btn-dark w-45" OnClick="btnClear_OnClick"/>

Login.aspx.cs 應該會自動加入事件,如果沒有可以手動加入,加入後像是這樣

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace PartyRegister.Admin
{
    public partial class Login : System.Web.UI.Page
    {
       
	protected void Page_Load(object sender, EventArgs e)
	{
	}

        protected void btnSubmit_OnClick(object sender, EventArgs e)
        {
            //送出事件寫在這邊
        }

        protected void btnClear_OnClick(object sender, EventArgs e)
        {
            //清除事件寫在這邊
        }
    }
}

加入這兩個事件後

btnSubmit_OnClick登入帳號密碼判定

/// <summary>
/// 管理者帳號 (臨時的)
/// </summary>
private const string account = "admin";

/// <summary>
/// 管理者密碼 (臨時的)
/// </summary>
private const string passwd = "admin123";

/// <summary>
/// 登入按鈕按下後的事件
/// </summary>
protected void btnSubmit_OnClick(object sender, EventArgs e)
{
    errorMsg.Text = "";
    if (
        tbAccount.Text.ToLower() == account &&
        tbPasswd == tbPasswd
    )
    {
        //登入成功
        //寫入Session
        Session.Add("User", account);//寫入

        //跳轉頁面
        Response.Redirect("Index.aspx");
    }
    //登入失敗
    errorMsg.Text = "登入失敗";
    tbAccount.Text = string.Empty;
    tbPasswd.Text = string.Empty;
}

幾個關鍵點說明

  1. 登入的帳號跟密碼寫在開頭用變數表示,這個做法在行內叫做寫死在程式內,相反的寫活就是存在資料庫當中。private是物件導向中,不能由外部存取,而const則表示這是一個常數
  2. 普遍上輸入帳號會不分大小些,因此會將帳號輸入轉小寫或轉大寫再進行判斷,在這邊我用的是轉小寫。
  3. 登入成功後會加入Session後跳轉,在Webform中Session用的非常普遍,用來存這使用者的登入資訊(後續我再解釋這個機制怎運作的)。不過比較現代的框架通常使用CookieJWT這兩種技術,較少使用Session。
  4. 登入失敗時會顯示登入失敗,目前資安考量上會清除帳密+只顯示失敗,不會顯示是缺少帳號還是密碼錯誤。

btnClear_OnClick清除資訊

protected void btnClear_OnClick(object sender, EventArgs e)
{
    errorMsg.Text = string.Empty;
    tbAccount.Text = string.Empty;
    tbPasswd.Text = string.Empty;
}

這邊比較簡單,就是清除而已

程式碼

Login.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Login.aspx.cs" Inherits="PartyRegister.Admin.Login" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <style>
        .login-container {
            min-height: 80vh;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .card {
            width: 100%;
            max-width: 400px;
            box-shadow: 0 0 20px rgba(0,0,0,0.05);
            border-radius: 10px;
        }

        .card-header {
            border-top-left-radius: 10px;
            border-top-right-radius: 10px;
        }

        .w-45 {
            width: 48%;
        }
        input{
            max-width: 100% !important;
        }
    </style>
    <div class="login-container">
        <div class="container">
            <div class="card mx-auto">
                <div class="card-header">
                    <h2 class="h5">後台管理登入</h2>
                </div>
                <div class="card-body">
                    <div class="row">
                        <div class="col-12">
                            <asp:Label runat="server" ID="errorMsg" ForeColor="red"></asp:Label>
                        </div>
                        <div class="col-12">
                            <div class="form-group">
                                <asp:Label runat="server" ID="lbAccount" Text="帳號"></asp:Label>
                                <asp:TextBox runat="server" ID="tbAccount" Text="" placeholder="請輸入帳號" CssClass="form-control w-100"></asp:TextBox>
                            </div>
                        </div>
                        <div class="col-12">
                            <div class="form-group">
                                <asp:Label runat="server" ID="lbPasswd" Text="密碼"></asp:Label>
                                <asp:TextBox runat="server" ID="tbPasswd" Text="密碼" TextMode="Password" CssClass="form-control w-100" placeholder="請輸入密碼" AutoCompleteType="Disabled"></asp:TextBox>
                            </div>
                        </div>
                        <div class="col-12">
                            <div class="form-group mt-3 d-flex justify-content-between">
                                <asp:Button runat="server" ID="btnSubmit" Text="登入" CssClass="btn btn-primary w-45" OnClick="btnSubmit_OnClick" />
                                <asp:Button runat="server" ID="btnClear" Text="清除" CssClass="btn btn-dark w-45" OnClick="btnClear_OnClick"/>
                            </div>

                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</asp:Content>

Login.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace PartyRegister.Admin
{
	public partial class Login : System.Web.UI.Page
    {
        /// <summary>
        /// 管理者帳號 (臨時的)
        /// </summary>
        private const string account = "admin";

        /// <summary>
        /// 管理者密碼 (臨時的)
        /// </summary>
        private const string passwd = "admin123";
	protected void Page_Load(object sender, EventArgs e)
	{

	}

        protected void btnSubmit_OnClick(object sender, EventArgs e)
        {
            errorMsg.Text = "";
            if (
                tbAccount.Text.ToLower() == account.ToLower() &&
                tbPasswd == tbPasswd
            )
            {
                //登入成功
                //寫入Session
                Session.Add("User", account);//寫入

                //跳轉頁面
                Response.Redirect("Index.aspx");
            }
            //登入失敗
            errorMsg.Text = "登入失敗";
            tbAccount.Text = string.Empty;
            tbPasswd.Text = string.Empty;
        }

        protected void btnClear_OnClick(object sender, EventArgs e)
        {
            errorMsg.Text = string.Empty;
            tbAccount.Text = string.Empty;
            tbPasswd.Text = string.Empty;
        }
    }
}

🔍 Session 是什麼?

在 Web 世界中,HTTP 是無狀態的協議(stateless)。也就是說,使用者從 A 頁到 B 頁,伺服器是無法記得「你是誰」、「剛剛輸入了什麼」。

這時候就要靠 Session 來幫我們「記住使用者狀態」。

對瀏覽器來說Session是一把鑰匙,每次存取時候都把這把鑰匙傳給伺服器,讓伺服器檢查鑰匙後放行到你可以去的地方。

🧠 WebForm 的 Session 原理(用簡單流程解釋)

  1. 第一次訪問網站:
    • 使用者請求伺服器頁面(比如 Login.aspx)。
    • ASP.NET 會產生一個唯一的 Session ID(像一組亂碼)。
    • 這個 Session ID 會透過 Cookie(預設是 ASP.NET_SessionId 傳回給瀏覽器。
  2. 之後的每一次請求:
    • 瀏覽器自動附上這個 ASP.NET_SessionId Cookie。
    • ASP.NET 拿這個 ID 去伺服器的記憶體(或其他地方)找對應的 Session 資料
    • 這樣就能讀取之前儲存的內容(像登入者帳號、使用者偏好等)。

把上面這些簡單化畫成圖

Session


🔐 Session 是存在哪裡?

ASP.NET 提供幾種方式儲存 Session 資料(可以設定):

儲存方式優點缺點
InProc(預設)速度快重開 IIS、AppPool 就會消失
StateServer跨網站共用、不怕重開 IIS設定比較複雜
SQLServer不怕重開 IIS、安全性高效能略低
Custom Provider可客製化儲存方式自己開發與維護

0 Comments

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *