使用ActionFilterAttribute抽象類別。實作IP過濾

使用ActionFilterAttribute抽象類別並覆寫OnActionExecuting。實作IP過濾

覆寫OnActionExecuting虛擬方法

先繼承ActionFilterAttribute 抽象類別,並覆寫虛擬方法OnActionExecuting。

透過參數ActionExecutingContext取得遠端IP位置,進行IP篩選。

IP位置不符合篩選條件,則回傳一個ContentResult,ContentResult可以自行定義ContentType(MIME)。這裡我們的ContentType設成存文字text/pain,並設定錯誤訊息ip not allowed!!。

順帶一提!!

base.OnActionExecuting(context)這一行依據這篇文章(Why call base.OnActionExecuting(filterContext);?)來看的話是可以註解掉,因為如果回去看原始碼,base.OnActionExecuting()這個虛擬方法(註:虛擬方法裡面可以實做程式碼,跟介面不同)裡面是沒有任何程式碼的。所以就算不加上去也是不會有任何影響的。

但我這裡是建議加上他的,至於是什麼原因,我們在另外一篇文章在來說(傳送門:ActionFilter的流程以及ActionFilter流程結束時間點)。

	using Microsoft.AspNetCore.Mvc;
	using Microsoft.AspNetCore.Mvc.Filters;
    
	public class AllowedIpAttribute: ActionFilterAttribute
    {
        private string[] ipList = new string[] { };

        public AllowedIpAttribute(string allowedIps)
        {
            ipList = allowedIps.Split(',', ';');
        }

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            var clientIp = context.HttpContext.Connection.RemoteIpAddress.ToString();            

            if (!ipList.Contains(clientIp)) 
            {
                context.Result = new ContentResult()
                {
                    StatusCode = 400,
                    Content = "ip not allowed!!",
                    ContentType = "text/plain; charset=utf-8"
                };
            }

            base.OnActionExecuting(context);
        }
    }

指定API(Action)掛載Attribute

		private const string _allowIpList = "172.21.130.8,172.22.136.54,172.22.136.97,::1,127.0.0.1";

        [HttpGet]

        [Filters.AllowedIp(_allowIpList)]
     
        public async Task TestAPI()
        {           

			...
        }

接收錯誤訊息

這便我們接收的catch類別要換成WebException才能取得錯誤訊息的文字串流。用一般常用的Exception類別會無法取得。

		try
        {
        	呼叫TestAPI...
		}
		catch (WebException exWeb)
		{
			using (var response = exWeb.Response.GetResponseStream())
			{
				using (var sr = new StreamReader(response, Encoding.UTF8))
				{
					var responseMsg = sr.ReadToEnd().ToString();
					response.Close();                                                                                                    
					filterContext.Result = new HttpStatusCodeResult((exWeb.Response as HttpWebResponse).StatusCode, $"darType OnActionExecuting error:{responseMsg}");
				}
			}
		}

 

Ref:

  1. 介面(Interface). 抽象(Abstract). 虛擬(Virtual)的差異
  2. Why call base.OnActionExecuting(filterContext);?
  3. ASP.NET MVC中的ActionFilter是如何执行的?