[.net MVC C#] 登入功能使用表單驗證(FormsAuthentication) 實作筆記

簡易的達成前端送出時欄位驗證

以及後端登入驗證

實作方式的紀錄

前置作業

 

首先建一個Model

設定一些前端驗證規則給前端用
因為沒有要實作撈DB資料那段所以把後端模擬測試用的CODE也在在這裡

public class MyAccount
{
	[Required]
	[StringLength(6, ErrorMessage = "帳號不能大於6碼!")]
	[Display(Name = "帳號")]
	public string UserName { get; set; }
	[Required]
	[StringLength(6, ErrorMessage = "密碼不能大於6碼!")]
	[Display(Name = "密碼")]
	public string Password { get; set; }
	public int Rank { get; set; }
	public MyAccount(string _UserName,string _Password)
	{
		string simulatio_DB_Password = "abc123"; //假裝從DB撈回來的
		if (_Password == simulatio_DB_Password)
		{
			this.UserName = _UserName;
			this.Password = simulatio_DB_Password;
			this.Rank = 0;
		}
	}
}

開始做VIEW的部分

step1. 先到controller中建立一個ActionResult

public ActionResult Logon()
{

	return View();
}

接著右鍵新增view

step2. 在Logno.cshtml中加入帳號密碼輸入欄位..等

@using (Html.BeginForm("Logon", "Home", FormMethod.Post))
{
    /*
     AntiForgeryToken可防止CSRF攻擊,前端放一把鑰匙
     後端有個對應的門鎖[ValidateAntiForgeryToken]
     沒有鑰匙就無法通過
     用來防止偽造的請求
     */
    @Html.AntiForgeryToken()

    @Html.LabelFor(x => x.UserName) //<--標題
    @*@Html.DisplayNameFor(x => x.UserName) //也可以用這個*@
    @Html.TextBoxFor(x => x.UserName) //<--Input text 欄位
    @Html.ValidationMessageFor(x => x.UserName) //<--驗證訊息

    @Html.LabelFor(x => x.Password) //<--標題
    @Html.PasswordFor(x => x.Password) //input password 欄位
    @Html.ValidationMessageFor(x => x.Password) //<--驗證訊息

    <input type="submit" />
}

step3. 在Logno.cshtml下方加入Script (少了這支前端就沒有驗證功能了)

@section scripts{
    @Scripts.Render("~/bundles/jqueryval")
}
再來做Controller的部分

Logon的ActionResult會有2個

一個會判斷(判斷的程式在文章後段)是否登入,否的話就return登入畫面 
另一個是填妥帳密後接收Post資料並做處理

public ActionResult Logon()
{
   if(_LogonStatus.isSigned())
	{
		return Content("PASS");
	}

	return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Logon(FormCollection LogonCollection)
{

	var UserName = LogonCollection["UserName"].ifNulltoEmpty();
	var Password = LogonCollection["Password"].ifNulltoEmpty();

	// 登入的密碼(以 SHA1 加密)
	//var PasswordSHA = FormsAuthentication.HashPasswordForStoringInConfigFile(Password, "SHA1");

	//這一條是去資料庫抓取輸入的帳號密碼的方法請自行實做
	//var myAcc = account.GetSingleAccount(acc, Password);

	//做一個假的範例用
	var myAcc = new MyAccount(UserName, Password);
	// 登入時清空所有 Session 資料
	Session.RemoveAll();

	FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
	myAcc.UserName,//你想要存放在 User.Identy.Name 的值,通常是使用者帳號
	DateTime.Now,
	DateTime.Now.AddMinutes(30),
	false,//將管理者登入的 Cookie 設定成 Session Cookie
	myAcc.Rank.ToString(),//userdata看你想存放啥
	FormsAuthentication.FormsCookiePath);

	string encTicket = FormsAuthentication.Encrypt(ticket);

	Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));

	return RedirectToAction("TestIsLogon", "Home");
	//return View();
}

補充:關於ifNulltoEmpty

接著做兩個測試的

第一個

建一個測試用的ActionResult 命名為TestIsLogon 在上面加上attribute [Authorize]

[Authorize]
public ActionResult TestIsLogon()
{
	return Content("PASS");
}

測試在未登入成功的情況下

測試在登入成功的情況下

 

第二個

先製作一段驗證登入的程式

namespace tryUserLogon.Extensions
{
    public class LogonStatus
    {
        public bool isSigned() {
            var context = HttpContext.Current;
            if(context.User != null)
            {
                var formIdentify = context.User.Identity as FormsIdentity;
                bool IsAuthenticated = context.User.Identity.IsAuthenticated;
                if (formIdentify != null && IsAuthenticated)
                {
                    return true;
                }
            }
            return false;
        }
    }
}

在Controller中先New出LogonStatus物件,然後再index 中測試看看

public class HomeController : Controller
{
	LogonStatus _LogonStatus = new LogonStatus(); //<--先NEW出LogonStatus物件
	public ActionResult Index()
	{
		ViewData["IsAuthenticated"] = "未登入";
		if (_LogonStatus.isSigned())
		{
			ViewData["IsAuthenticated"] = "已登入";
		}

		return View();
	}
}

未登入

已登入

 

補充ifNulltoEmpty

這是一段自己客製的擴充方法

namespace tryUserLogon.Extensions
{
    public static class NulltoEmptyExtension
    {
        public static string ifNulltoEmpty(this string str)
        {
            return str ?? "";
        }
    }
}

範例檔:
https://bitbucket.org/yu_allen/logonformsauthenticationexercise