跟mvc一樣,webapi大多通過附加Authorize特性來實現授權,Authorize當授權失敗時返回狀態碼:401。一般系統狀態為401時,服務端就Redirect重定向到登錄頁。
問題來了,我們的webapi在為富客戶端ajax提供服務時,合理的做法是無論服務端發生什么情況,都盡可能給客戶端返回json,才方便ajax回調函數解析。而重定向到登錄了,則將返回登錄頁的一串html,ajax回調函數就傻傻的分不清楚啦。
當然,解決辦法是有的,思路為:重寫Authorize的HandleUnauthorizedRequest,讓服務端返回json,並且把狀態碼401改為其他狀態碼來避免被重定向。最合理的是改為403,表示服務器拒絕。
重寫Authorize有以下幾個要點需注意:
- HandleUnauthorizedRequest中基類方法已經將Response的狀態設為”HttpStatusCode.Unauthorized(即401)“,重寫時手請動改為”HttpStatusCode.Forbidden(即403)“,否則按401狀態往下執行,就要被重定向到登錄頁;
- webApi下的授權篩選attribute為System.Web.Http.AuthorizeAttribute,而Mvc下用的是System.Web.Mvc.AuthorizeAttribute。這里別繼承錯了,否則授權篩選attrbute攔截不了。
- WebApi下Authorize.HandleUnauthorizedRequest的參數filterContext在此上下文里response還為空,需要手動創建。
以下是我重寫的Authorize:
1 /// <summary> 2 /// 重寫實現處理授權失敗時返回json,避免跳轉登錄頁 3 /// </summary> 4 public class ApiAuthorize : AuthorizeAttribute 5 { 6 protected override void HandleUnauthorizedRequest(HttpActionContext filterContext) 7 { 8 base.HandleUnauthorizedRequest(filterContext); 9 10 var response = filterContext.Response = filterContext.Response ?? new HttpResponseMessage(); 11 response.StatusCode = HttpStatusCode.Forbidden; 12 var content = new Result 13 { 14 success = false, 15 errs = new[] { "服務端拒絕訪問:你沒有權限,或者掉線了" } 16 }; 17 response.Content = new StringContent(Json.Encode(content), Encoding.UTF8, "application/json"); 18 } 19 }
運行結果:



chrome下查看返回狀態:


Demo已經上傳,需要的朋友請點擊下載:
示例源碼