標籤:des style c class blog code
與ActionFilter相關的介面有2個:
□ IActionFilter 對action執行前後處理
void OnActionExecuting(ActionExecutingContext filterContext);
可以在此對請求處理,甚至開啟一個新的請求。
void OnActionExecuted(ActonExecutedContext filterContext);
可以在此對返回結果處理,甚至取消返回結果。
關於參數ActionExecutingContext和ActonExecutedContext共有的:
都繼承於ControllerContext。
都有ActionDescriptor屬性:提供了action的細節
都有ActionResult屬性:當設定為null的時候取消整個請求
關於ActonExecutedContext專屬的:
Canceled屬性:bool類型,ActionExecutedContext是否被其它action filter取消
Exception屬性:action filter和action拋出的異常
ExceptionHandled屬性:bool類型,異常是否被處理
□ IResultFilter 對action返回結果前後做處理
方法與屬性與IActionFilter類似。
void OnResultExecuted(ResultExecutedContext filterContext);
void OnResultExecuting(ResultExecutingContext filterContext);
執行個體:繼承ActionFilterAttribute為登入密碼加密
ActionFilterAttribute包含了如下4個方法:
void OnActionExecuting(ActionExecutingContext filterContext);
void OnActionExecuted(ActonExecutedContext filterContext);
void OnResultExecuted(ResultExecutedContext filterContext);
void OnResultExecuting(ResultExecutingContext filterContext);
所以,我們可以在衍生類別中重寫這4個方法。
□ 思路
→在執行action之前對密碼加密
→在執行action之後,根據是否登入成功,來決定返回成功或重新登入視圖
→在action返回結果之後,再追加一些內容
□ 繼承ActionFilterAttribute
using System;
using System.Security.Cryptography;
using System.Text;
using System.Web.Mvc;
using System.Web.Security;
namespace MvcApplication1.Extension
{
public class EncryptLoginAttribute : ActionFilterAttribute
{
private string username;
private string password;
private bool isAuthorized = false;
private string longdate;
private string lastTry;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
username = filterContext.HttpContext.Request.Form["username"];
password = filterContext.HttpContext.Request.Form["password"];
MD5 md5Hash = MD5.Create();
string md5Password = GetMD5Hash(md5Hash, password);
bool result = Membership.ValidateUser(username, md5Password);
if (result)
{
FormsAuthentication.SetAuthCookie(username, false);
isAuthorized = true;
longdate = DateTime.Now.ToLongDateString();
}
else
{
isAuthorized = false;
lastTry = DateTime.Now.ToShortDateString() + "-" + DateTime.Now.ToShortTimeString();
}
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (isAuthorized)
{
filterContext.Result = new ViewResult(){ViewName = "Welcome"};
}
else
{
ViewResult result = new ViewResult();
result.ViewName = "Index";
result.ViewBag.message = "Login fail";
filterContext.Result = result;
}
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (filterContext.Exception == null && !filterContext.Canceled)
{
ViewResult result = (ViewResult)filterContext.Result;
if (result != null)
{
if (result.ViewName == "Welcome")
{
filterContext.HttpContext.Response.Write("<p style=‘color:Green;‘><br/>Today is "
+ longdate + "<br/></p>");
}
else if (result.ViewName == "Index")
{
filterContext.HttpContext.Response.Write("<p style=‘color:Red;‘><br />Last Login attemp at "+lastTry+"<br/></p>");
}
filterContext.Result = result;
}
}
}
private static string GetMD5Hash(MD5 md5Hash, string input)
{
//string→byte[]
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder stringBuilder = new StringBuilder();
foreach (byte b in data)
{
stringBuilder.Append(b.ToString("x2"));
}
return stringBuilder.ToString();
}
}
}
□ HomeController
using System.Web.Mvc;
using System.Web.Security;
using MvcApplication1.Extension;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[EncryptLogin]
public ActionResult Login(string username, string password)
{
//TODO:儲存到資料庫
return null;
}
public ActionResult SignOut()
{
FormsAuthentication.SignOut();
return RedirectToAction("Index");
}
}
}
□ Home/Index.cshtml為登入頁
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<p style="color: red;">@ViewBag.message</p>
@using (Html.BeginForm("Login", "Home", FormMethod.Post, new {id = "loginForm"}))
{
<p>
使用者名稱:@Html.TextBox("username", null, new {style = "width:100px"})
</p>
<p>
密碼: @Html.Password("password", null, new {style = "width: 100px"})
</p>
<p>
<input type="submit" name="login" value="登入"/>
</p>
}
□ web.config相關配置
<authentication mode="Forms">
<forms loginUrl="~/Home/Index" timeout="2880">
<credentials passwordFormat="Clear">
<user name="name" password="21218cca77804d2ba1922c33e0151105"/>
</credentials>
</forms>
</authentication>
□ 登入成功視圖:/Shared/Welcome.cshtml
@{
ViewBag.Title = "Welcome";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>登入成功~~</h2>
@Html.ActionLink("登出","SignOut","Home")
登入頁:
登入失敗:
□ 如果想在全域使用
filters.Add(new EncryptLoginAttribute());
□ 備忘
暫沒有把登入成功顯示頁面調試出來,因為,當使用FormsAuthentication.Authenticate(username, md5Password)時,提示此方法已經過時;而使用Membership.ValidateUser(username, md5Password)時,對應的Web.config如何配置,暫沒細究。
參考資料:
MVC Filters Part 3 - Action Filter and Action Result Filter