標籤:cep and 邏輯 public 開發 nts ken 使用者名稱 並且
在WEB Api中,引入了面向切面編程(AOP)的思想,在某些特定的位置可以插入特定的Filter進行過程攔截處理。引入了這一機制可以更好地踐行DRY(Don’t Repeat Yourself)思想,通過Filter能統一地對一些通用邏輯進行處理,如:許可權校正、參數加解密、參數校正等方面我們都可以利用這一特性進行統一處理,今天我們來介紹Filter的開發、使用以及討論他們的執行順序。
一、Filter的開發和調用
在預設的WebApi中,架構提供了三種Filter,他們的功能和運行條件如下表所示:
Filter 類型 |
實現的介面 |
描述 |
Authorization |
IAuthorizationFilter |
最先啟動並執行Filter,被用作請求許可權校正 |
Action |
IActionFilter |
在Action啟動並執行前、後運行 |
Exception |
IExceptionFilter |
當異常發生的時候運行 |
首先,我們實現一個AuthFilterOutside可以用以簡單的許可權控制:
public class AuthFilterOutside: AuthorizeAttribute { private SP_PortUserBLL sp_portuserbll = new SP_PortUserBLL(); //重寫基類的驗證方式,加入我們自訂的Ticket驗證 public override void OnAuthorization(HttpActionContext actionContext) { //url擷取token var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase; HttpRequestBase request = content.Request; string access_key = request.Form["access_key"];//擷取請求參數對應的值 string sign = request.Form["sign"]; if (!string.IsNullOrEmpty(access_key) && !string.IsNullOrEmpty(sign)) { //解密使用者ticket,並校正使用者名稱密碼是否匹配 if (ValidateTicket(access_key, sign)) { base.IsAuthorized(actionContext); } else { HandleUnauthorizedRequest(actionContext); } } //如果取不到身分識別驗證資訊,並且不允許匿名訪問,則返回未驗證401 else { var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>(); bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute); if (isAnonymous) base.OnAuthorization(actionContext); else HandleUnauthorizedRequest(actionContext); } } //校正sign(資料庫資料匹配) private bool ValidateTicket(string key,string sign) { var result=sp_portuserbll.GetAccess_secret(key); if (!string.IsNullOrEmpty(result)) { var mysing= Encryption.DataEncryption(key, result);//sign驗證 if (mysing.Equals(sign)) { return true; } return false; } return false; } }
當請求地址裡麵包含 access_key 和 sign 對應的索引值對,擷取對應的值與資料庫資料進行匹配,匹配通過後可請求資料,適用於get 、post請求。
介面請求成功後記錄日誌的實現
/// <summary> /// 請求成功後觸發 /// </summary> public class AuthFilter: ActionFilterAttribute { private PortLogBLL portlogbll = new PortLogBLL(); public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { //action 請求之後觸發
//日誌記錄 訪問量記錄等等 portlogbll.SaveForm(new PortLogEntity() { PortName = actionExecutedContext.Request.RequestUri.AbsolutePath,//獲得調用介面, RequestType = actionExecutedContext.Request.Method.ToString(), StatusCode = Convert.ToInt32(new HttpResponseMessage(HttpStatusCode.OK).StatusCode),//設定狀態代碼 ClientIp = GetClientIp(), ParameterList = actionExecutedContext.ActionContext.ActionArguments.ToJson(),//獲得參數值 Success = true }); } /// <summary> /// 擷取用戶端Ip /// </summary> /// <returns></returns> private string GetClientIp() { string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.UserHostAddress; } if (string.IsNullOrEmpty(result)) { return "0.0.0.0"; } return result; } }
當服務端代碼報錯或出異常時,可自訂設定固定格式的異常返回給調用者
/// <summary> /// 介面發生異常過濾器 /// </summary> public class ExceptionHandling : ExceptionFilterAttribute, IExceptionFilter { private PortLogBLL portlogbll = new PortLogBLL(); public override void OnException(HttpActionExecutedContext actionExecutedContext) { var code = new HttpResponseMessage(HttpStatusCode.InternalServerError).StatusCode;//設定錯誤碼:例如:500 404 actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError); string msg = JsonConvert.SerializeObject(new BaseResult() { success = false, message = actionExecutedContext.Exception.Message });//返回異常錯誤提示 //寫入錯誤記錄檔相關實現 portlogbll.SaveForm(new PortLogEntity() { PortName = actionExecutedContext.Request.RequestUri.AbsolutePath, RequestType = actionExecutedContext.Request.Method.ToString(), StatusCode = Convert.ToInt32(code), ClientIp = GetClientIp(), ParameterList = actionExecutedContext.ActionContext.ActionArguments.ToJson(), Success = false, ErrorMessage = msg }); //result actionExecutedContext.Response.Content = new StringContent(msg, Encoding.UTF8); } /// <summary> /// 擷取調用介面者ip地址 /// </summary> /// <returns></returns> private string GetClientIp() { string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.UserHostAddress; } if (string.IsNullOrEmpty(result)) { return "0.0.0.0"; } return result; } } public class BaseResult { /// <summary> /// 狀態 /// </summary> public bool success { get; set; } /// <summary> /// 錯誤資訊 /// </summary> public string message { get; set; } }
以上是開發webapi常用代碼,自己封裝一下就可以使用了
C# WebApi 過濾器的使用開發介面必備利器