# 解決 Cookie 過期後,表單 Token Exception (ValidateAntiForgeryToken) ###### tags: `被玩壞了` ## 頁面產生的 Token 是有跟登入的 Cookie 連結的 ![](https://i.imgur.com/D8firRJ.png) 可能的情況可能是↓ 1. 登入後 -> 上一頁 -> 在登一次 ( 如圖,原本登入的頁面是沒 User.Identity 的,在登一次的時候,表單的 User.Identity 已經有值,自然匹配不到 ) 2. 停留在表單頁面至 Cookie 過期 -> 送出表單 ( 和圖片相反,原本表單的頁面是有包含 User.Identity 的 Token ,送出表單時,已經沒有 User.Identity,自然匹配不到 ) ※跟圖片相反的話是這樣(情況2) =>提供的反仿冒語彙基元是針對使用者 "20200506103622983001",但是目前的使用者是 ""。 ## 解決方案 情況1(已經登入中): 案上一頁硬要登,擷取錯誤(OnException),強行把他導回首頁 情況2(已經是未登入狀態): 擷取錯誤(OnException),導向至 Login ## Code ### BaseController Override onException ``` protected override void OnException(ExceptionContext filterContext) { Logger.Error(filterContext.Exception); // 如果登入 Cookie 過期 or 有可能案上一頁又在登入一次,造成表單防偽驗證失敗拋出 Exception,導回 Login 頁面重新登入 if (filterContext.Exception is HttpAntiForgeryException) { // 如果是登入中又在一次登入 if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated) { // 取得 RouteConfig 名為 Home 的 RouteMap filterContext.Result = new RedirectResult(Url.RouteUrl("Home")); } else { // 取得剛剛 Exception 前的表單 Url var returnUrl = filterContext.HttpContext.Request.Path; // 取得 RouteConfig 名為 Login 的 RouteMap var loginUrl = Url.RouteUrl("Login"); if (string.IsNullOrEmpty(returnUrl)) filterContext.Result = new RedirectResult(loginUrl); else filterContext.Result = new RedirectResult($"{loginUrl}?ReturnUrl={returnUrl}"); } // 表示已經處理此例外事件 filterContext.ExceptionHandled = true; } else { base.OnException(filterContext); } } ``` ### RouteConfig ![](https://i.imgur.com/A7Bq8qo.png) ``` routes.MapRoute( name: "Login", url: "Member/Login", defaults: new { controller = "Member", action = "Login" }); routes.MapRoute( name: "Home", url: "Home/Index", defaults: new { controller = "Home", action = "Index" }); ```