從 上一篇 其實能看到, 程序執行的過濾器, 有四種 :
過濾器類型
接口
描述
Authorization
IAuthorizationFilter
此類型(或過濾器)用於限制進入控制器或控制器的某個行為方法
Exception
IExceptionFilter
用於指定一個行為,這個被指定的行為處理某個行為方法或某個控制器裡面拋出的異常
Action
IActionFilter
用於進入行為之前或之後的處理
Result
IResultFilter
用於返回結果的之前或之後的處理
但是默認實現它們的過濾器只有三種,分別是Authorize(授權),ActionFilter,HandleError(錯誤處理);各種信息如下表所示
過濾器
類名
實現接口
描述
ActionFilter
AuthorizeAttribute
IAuthorizationFilter
此類型(或過濾器)用於限制進入控制器或控制器的某個行為方法
HandleError
HandleErrorAttribute
IExceptionFilter
用於指定一個行為,這個被指定的行為處理某個行為方法或某個控制器裡面拋出的異常
自定義
ActionFilterAttribute
IActionFilter和IResultFilter
用於進入行為之前或之後的處理或返回結果的之前或之後的處理
下面就來介紹一下這幾種過濾器.
一、授權過濾器 Authorize
1. 方式一 : Controller類中的 OnAuthorization 方法
我們新建的控制器類裡面, 都會直接或者間接繼承自 Controller 類, 那麼在Controller裡面, 有一個 OnAuthorization 方法, 這個方法也是授權過濾器裡面的.
// 摘要: // 定義授權篩選器所需的方法。 public interface IAuthorizationFilter { // 摘要: // 在需要授權時調用。 // // 參數: // filterContext: // 篩選器上下文。 void OnAuthorization(AuthorizationContext filterContext); }
這種方式, 是不需要在 FilterConfig 文件中, 配置自己的過濾器的.
我先建一個特性, 只要方法加上此特性, 都是不需要登錄驗證的.
public class AllowLoginAttribute : Attribute { }
裡面沒有任何的內容, 也不需要什麼內容.
然後就是過濾器方法了.
public class HomeController : Controller { protected override void OnAuthorization(AuthorizationContext filterContext) { var attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowLoginAttribute), true); if (attrs.Count() > 0) { return; } var cookie = Request.Cookies["Login"]; if (cookie == null || cookie.Value != "Already Login") {
//正如前面解析的, 只需要給Result賦值, 就可以影響MVC走的流程 filterContext.Result = RedirectToAction("Login"); } }
//此方法會給浏覽器一個 Cookie, 用來識別是否已登錄身份的
//實際使用中, 可以做成登錄頁面, 要求登錄, 然後給Cookie和Session [AllowLogin] public ActionResult Login() { HttpCookie cookie = new HttpCookie("Login", "Already Login"); cookie.Expires = DateTime.Now.AddMinutes(3); Response.Cookies.Add(cookie); return View(); }
//這裡就是我想要訪問的頁面了 public ActionResult Index() { return View(); } }
接下來, 我先直接訪問Index頁面看一下:
直接跳轉到登陸頁面了, 此時, 浏覽器已經得到想要的Cookie了, 這時候, 再去訪問Index頁面看看.
成功訪問.
由於這種方式是寫在控制器裡面的, 所以就只對控制器裡面的方法有效, 也就是說, 如果此時我訪問一個別的控制器, 這種方法就不起作用了.
那麼, 我是不是要在每個控制器裡面寫一遍? 或者我自己弄一個控制器父類, 讓別的類來繼承我寫的類? 是不是有點太麻煩了了.
腫麼辦呢? 方法就在下面
2. 方式二 : AuthorizeAttribute 的 OnAuthorization 方法
方法裡面的內容和上面其實是一樣的, 只不過這個方法存放的位置不一樣.
但是有幾個不一樣的地方.
2.1 需要在FilterConfig中注冊自己的過濾器
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new MyAuthAttribute()); filters.Add(new HandleErrorAttribute()); } }
2.2 跳轉的時候, 稍有不同
public class MyAuthAttribute : AuthorizeAttribute {public override void OnAuthorization(AuthorizationContext filterContext) { var attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowLoginAttribute), true); if (attrs.Count() > 0) { return; } var cookie = HttpContext.Current.Request.Cookies["Login"]; if (cookie == null || cookie.Value != "Already Login") { filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { controller = "Home", action = "Login" })); return; } } }
2.3 最好在Web.config文件中修改下配置.
<system.web> <authentication mode="Forms"> <forms loginUrl="~/Home/Login" timeout="2880" /> </authentication> </system.web>
我自測過了, 是可以的. 結果就不貼了, 看不出什麼別的. 和上面是一樣的.
3. 方式三 : AuthorizeAttribute 的 AuthorizeCore 方法
這個方法就簡單了, 只要返回false, 就回按照上面配置文件配置的去跳轉. 一般都會將這裡的 OnAuthorization 和 AuthorizeCore 方法一起用.
來看一下代碼:
public class MyAuthAttribute : AuthorizeAttribute {
//在這個方法中, 我判斷了用戶是否已經登錄 protected override bool AuthorizeCore(HttpContextBase httpContext) { bool isAuth = httpContext.User.Identity.IsAuthenticated; return isAuth; }
//在這個方法中, 我判斷了 Action 是否需要 登錄 public override void OnAuthorization(AuthorizationContext filterContext) { var attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowLoginAttribute), true); if (attrs.Count() > 0) { return; } base.OnAuthorization(filterContext); } }
然後要修改一下HomeController控制器中的Login方法.
[AllowLogin] public ActionResult Login() {
//執行這個方法之後, Identity 的那裡才能得到 true FormsAuthentication.SetAuthCookie("Login", false); return View(); }
目錄已同步