使用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是如何执行的?