[Learning] DOTNET 5 自訂帳號登入驗證

測試如何在自己的專案加入登入驗證功能

概述

想要簡單測試自訂的方式進行登入驗證, 並且將登入功能製成 Area 的方式測試,順便測試登入過時, 故進行簡單測試

 

內容

首先, 我們需要加入 "LoginExpireMinute": 5 在 AppSetting 內, 並且在 Startup 的 Configuration Service 加入讀取 App Setting 的逾時變數

// Get AppSetting Value
double LoginExpireMinute = this.Configuration.GetValue<double>("LoginExpireMinute");

// Registe CookieAuthentication, Scheme
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(
         option =>
                {
                    option.LoginPath = new PathString("/Account/Login/Index");
                    option.LogoutPath = new PathString("/Home/Index");
                    
                    //Over Time
                    option.ExpireTimeSpan = TimeSpan.FromMinutes(LoginExpireMinute);
                });

除此之外, 我們還需要在 Configure 內加入驗證功能

// add Authentication
app.UseAuthentication();
app.UseAuthorization();

在 Endpoint 內加入 Area 的 Route 路徑

endpoints.MapAreaControllerRoute(
                    name: "areaAccount",
                    areaName: "Account",
                    pattern: "Account/{controller=Home}/{action=Index}/{id?}");

 

完成 Startup 的設定後, 我們在 _Layout <ul> 結束後加入 <partial name="_LoginPartial"> ,以便後續將 Login 與 Logout 隔開。

加入後, 新增一個 View 在 Shared 內並且命名 _LoginPartial。 這樣做的異動將會在上方列表的右方。 我們將新增後加入以下程式碼:

<ul class="navbar-nav">

    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Account" asp-controller="Login" asp-action="Logout">LogOut</a>
    </li>

    <li class="nav-item">
        <a class="nav-link text-dark" id="login" asp-area="Account" asp-controller="Login" asp-action="Index">Login</a>
    </li>

</ul>

 

完成後, 在專案下新增一個文件夾叫 Area 與在該文件夾右鍵新增 Area, 選擇 MVC 的架構並且命名為 Account。

完成即會長出與 MVC 相同的專案架構在 Account 文件夾內。

開啟 Account 內的 Views 並且新增一個 Login 文件夾已做頁面區分, 並且在內新增一個 Index 頁面以供登入功能做作用。

@model CustomLogin.Areas.Account.Models.LoginModel

@{
    ViewData["Title"] = "Login";
}

<h1>Login Account</h1>

    <div class="col-md-10 offset-1">
        
        <form asp-action="Index" method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>

            <div class="form-group">
                <div class="input-group">

                    <input asp-for="LoginAccount" class="form-control" />
                </div>
                <span asp-validation-for="LoginPassword" class="text-danger"></span>
            </div>
            
            <div class="form-group">
                <div class="input-group">
  
                    <input asp-for="LoginPassword" class="form-control" />
                </div>
                <span asp-validation-for="LoginPassword" class="text-danger"></span>
            </div>

            <div class="form-group">
                <button type="submit" class="btn btn-primary btn-block">Log In</button>
            </div>
            <div style="color:red;">
                @ViewData["errMsg"]
            </div>
        </form>
    </div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

完成後, 將 Shared 內的 _ValidationScriptsPartial 與 View 以下的 _ViewStart 與 _ViewImport 複製一份至 Account/Views 下,以便讀取界面設定

 

Views 設定結束後, 我們開始設定 Models,在 Account / Models 內創建一個 LoginModel 的類別,並加入:

public class LoginModel
    {
        public String LoginAccount { get; set; }
        public String LoginPassword { get; set; }
    }

 

完成後, 在 Controller 創建一個 LoginController 並在內進行設計驗證功能。 

[Area("Account")]
    [AutoValidateAntiforgeryToken]
    public class LoginController : Controller
    {
        // get appsetting
        private readonly IConfiguration config;

        public LoginController(IConfiguration config)
        {
            this.config = config;
        }
        
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Index(LoginModel login)
        {
            // check model
            if (ModelState.IsValid)
            {

                // check account
                if (((login.LoginAccount == "test") && (login.LoginPassword == "test")) == false)
                {
                    ViewBag.errMsg = "Login Fail";

                    return View();
                }
                else
                {
                    // get login account
                    Claim[] claims = new[] { new Claim("Account", login.LoginAccount) };

                    // scheme
                    ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                    
                    // Login
                    ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);


                    // get over setting value
                    double loginExpireMinute = this.config.GetValue<double>("LoginExpireMinute");

                    // IsPersistent = false,web will close and logout
                    // if web over setting will logout
                    /* ExpiresUtc = DateTime.Now.AddMinutes(loginExpireMinute) */
                     await HttpContext.SignInAsync(principal, new AuthenticationProperties() { IsPersistent = false, });

                    return Redirect("/Home/Index");
                }
            }
            else
            {
                ViewData["errMsg"] = "Please Input";

                return View();
            }
        }

        public async Task<IActionResult> Logout()
        {
            //logout
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return Redirect("/Home/Privacy");
        }

以上完成後即可進行測試,即時完成相關自訂帳號驗證功能。中間可能有其他可以強化的地方,但是主要是測試功能, 將不多加以設計。

 

參考文件

[ASP.net Core 3.0] 實作 Cookie based 登入機制(CookieAuthentication) 取代ASP.Net Framework的表單驗證(FormsAuthentication)登入 - https://dotblogs.com.tw/shadow/2019/01/16/105615

 

完整專案 - https://github.com/RyukHau/CustomLogin

 

感謝閱讀

分級: 入門是認識, 基本是運用, 進階是混合結合
範本是已可下載或可使用的範例, 至於教程當然是學習的結晶