session 與 cookies 登入機制
一、session
1、一個基本的session登入架構
架構圖僅供參考,跟程式無關。
一個最基本的登入機制原理就是「後台登入」,
因為後臺可以用來新增文章、上架商品因此有必要設置登入機制來過濾一般人進入,
而登入機制可以利用session技術來完成,
以下程式是用來說明session用法,檔案結構如下
HomeController.cs 為
using System;
using System.Web.Mvc;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
if (Convert.ToBoolean(Session["auth"]) == true)
{
ViewBag.Name = Session["Name"].ToString();
return View();
}
else
{
ViewBag.Name = "Guest";
return View();
}
}
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(string myid)
{
Session["auth"] = true;
Session["Name"] = myid;
return RedirectToAction("Index");
}
public ActionResult Logout()
{
Session["auth"] = false;
ViewBag.Name = "Guest";
return View("Index");
}
public ActionResult About()
{
if (Convert.ToBoolean(Session["auth"]) == true)
{
ViewBag.Name = Session["Name"].ToString();
return View();
}
else
{
ViewBag.Name = "Guest";
return View();
}
}
}
}
_Layout.cshtml 的內容為
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> @{ if (Convert.ToBoolean(Session["auth"]) == true) { <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("登出", "Logout", "Home", null, new { @class = "btn btn-default" })</li> </ul> } else { <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("登入", "Login", "Home", null, new { @class = "btn btn-link" })</li> </ul> } } </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
Index.cshtml 的內容為
@{ ViewBag.Title = "Home Page"; } <p style="color:red;">Hello! @ViewBag.Name</p> <div class="jumbotron"> <h1>ASP.NET</h1> <p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p> <p><a href="https://asp.net" class="btn btn-primary btn-lg">Learn more »</a></p> </div> <div class="row"> <div class="col-md-4"> <h2>Getting started</h2> <p> ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development. </p> <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301865">Learn more »</a></p> </div> <div class="col-md-4"> <h2>Get more libraries</h2> <p>NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.</p> <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301866">Learn more »</a></p> </div> <div class="col-md-4"> <h2>Web Hosting</h2> <p>You can easily find a web hosting company that offers the right mix of features and price for your applications.</p> <p><a class="btn btn-default" href="https://go.microsoft.com/fwlink/?LinkId=301867">Learn more »</a></p> </div> </div>
About.cshtml 的內容為
@{ ViewBag.Title = "About"; } <h2>@ViewBag.Title</h2> <h3 style="color:red;">@ViewBag.Name</h3> <p>Use this area to provide additional information.</p>
Login.cshtml 的內容為
<br /> <form action="@Url.Action("Login")" method="post" class="form-inline"> <div class="form-group"> <label for="myid" class="control-label">請輸入登入名稱</label> <input id="myid" name="myid" type="text" class="form-control" /> <input class="btn btn-primary" type="submit" value="登入" /> </div> </form>
2、我們可以利用 Authorization Filter 來讓程式變得更簡潔,
承上例,我們新增一個自訂的 Filter,檔名為 AuthorizePlusAttribute.cs,檔案結構如下
AuthorizePlusAttribute.cs 的內容為
using System;
using System.Web.Mvc;
namespace WebApplication1.Filter
{
public class AuthorizePlusAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (Convert.ToBoolean(filterContext.HttpContext.Session["auth"]) == true)
{
filterContext.Controller.ViewBag.Name = filterContext.HttpContext.Session["Name"].ToString();
}
else
{
HandleUnauthorizedRequest(filterContext);
}
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Controller.ViewBag.Name = "Guest";
}
}
}
HomeController.cs 重新改為
using System.Web.Mvc;
using WebApplication1.Filter;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
[AuthorizePlus]
public ActionResult Index()
{
return View();
}
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(string myid)
{
Session["auth"] = true;
Session["Name"] = myid;
return RedirectToAction("Index");
}
public ActionResult Logout()
{
Session["auth"] = false;
ViewBag.Name = "Guest";
return View("Index");
}
[AuthorizePlus]
public ActionResult About()
{
return View();
}
}
}
二、HttpCookie
承上部分程式再修改,實際應用如下
架構圖僅供參考,跟程式無關。
HomeController.cs
using System.Web.Mvc;
using WebApplication1.Filter;
using System;
using System.Web;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
[AuthorizePlus]
public ActionResult Index()
{
return View();
}
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(string myid)
{
Session["auth"] = true;
Session["Name"] = myid;
var theGuid = Guid.NewGuid().ToString();
DateTime validityPeriod = DateTime.UtcNow.AddSeconds(30d);
HttpContext.Application[theGuid] = validityPeriod;
var HttpCookie = new HttpCookie("myLogin", theGuid)
{
Expires = validityPeriod,
HttpOnly = true
};
Response.Cookies.Add(HttpCookie);
return RedirectToAction("Index");
}
public ActionResult Logout()
{
Session["auth"] = false;
ViewBag.Name = "Guest";
return View("Index");
}
[AuthorizePlus]
public ActionResult About()
{
return View();
}
}
}
AuthorizePlusAttribute.cs
using System;
using System.Web.Mvc;
namespace WebApplication1.Filter
{
public class AuthorizePlusAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
string theGuid = "";
try
{
theGuid = Convert.ToString(filterContext.HttpContext.Request.Cookies["myLogin"].Value);
}
catch (System.NullReferenceException)
{
theGuid = "";
}
if (Convert.ToBoolean(filterContext.HttpContext.Session["auth"]) == true && !string.IsNullOrWhiteSpace(theGuid) && CheckLoginTime(filterContext, theGuid))
{
filterContext.Controller.ViewBag.Name = filterContext.HttpContext.Session["Name"].ToString();
}
else
{
HandleUnauthorizedRequest(filterContext);
}
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Controller.ViewBag.Name = "Guest";
filterContext.HttpContext.Session["auth"] = false;
}
private Boolean CheckLoginTime(AuthorizationContext filterContext, string theGuid)
{
var loginTime = Convert.ToDateTime(filterContext.HttpContext.Application[theGuid]);
return (loginTime > DateTime.UtcNow) ? true : false;
}
}
}