C# 在 ASP.NET MVC Beta 中通过 IP 地址限制对特定控制器的访问

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/473687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 04:50:39  来源:igfitidea点击:

Restrict access to a specific controller by IP address in ASP.NET MVC Beta

c#asp.net-mvcsecurityweb-configauthorization

提问by Dylan Beattie

I have an ASP.NET MVC project containing an AdminController class and giving me URls like these:

我有一个 ASP.NET MVC 项目,其中包含一个 AdminController 类并为我提供如下 URls:

http://example.com/admin/AddCustomer

http://examle.com/Admin/ListCustomers

http://example.com/admin/AddCustomer

http://examle.com/Admin/ListCustomers

I want to configure the server/app so that URIs containing /Adminare only accessible from the 192.168.0.0/24 network (i.e. our LAN)

我想配置服务器/应用程序,以便只能从 192.168.0.0/24 网络(即我们的 LAN)访问包含/Admin 的URI

I'd like to restrict this controller to only be accessible from certain IP addresses.

我想将此控制器限制为只能从某些 IP 地址访问。

Under WebForms, /admin/ was a physical folder that I could restrict in IIS... but with MVC, of course, there's no physical folder. Is this achievable using web.config or attributes, or do I need to intercept the HTTP request to achieve this?

在 WebForms 下,/admin/ 是我可以在 IIS 中限制的物理文件夹……但是对于 MVC,当然,没有物理文件夹。这是否可以使用 web.config 或属性来实现,或者我是否需要拦截 HTTP 请求来实现这一点?

采纳答案by sabbour

I know this is an old question, but I needed to have this functionality today so I implemented it and thought about posting it here.

我知道这是一个老问题,但我今天需要有这个功能,所以我实现了它并考虑在这里发布它。

Using the IPList class from here (http://www.codeproject.com/KB/IP/ipnumbers.aspx)

使用这里的 IPList 类 ( http://www.codeproject.com/KB/IP/ipnumbers.aspx)

The filter attribute FilterIPAttribute.cs:

过滤器属性FilterIPAttribute.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Security.Principal;
using System.Configuration;

namespace Miscellaneous.Attributes.Controller
{

    /// <summary>
    /// Filter by IP address
    /// </summary>
    public class FilterIPAttribute : AuthorizeAttribute
    {

        #region Allowed
        /// <summary>
        /// Comma seperated string of allowable IPs. Example "10.2.5.41,192.168.0.22"
        /// </summary>
        /// <value></value>
        public string AllowedSingleIPs { get; set; }

        /// <summary>
        /// Comma seperated string of allowable IPs with masks. Example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0"
        /// </summary>
        /// <value>The masked I ps.</value>
        public string AllowedMaskedIPs { get; set; }

        /// <summary>
        /// Gets or sets the configuration key for allowed single IPs
        /// </summary>
        /// <value>The configuration key single I ps.</value>
        public string ConfigurationKeyAllowedSingleIPs { get; set; }

        /// <summary>
        /// Gets or sets the configuration key allowed mmasked IPs
        /// </summary>
        /// <value>The configuration key masked I ps.</value>
        public string ConfigurationKeyAllowedMaskedIPs { get; set; }

        /// <summary>
        /// List of allowed IPs
        /// </summary>
        IPList allowedIPListToCheck = new IPList();
        #endregion

        #region Denied
        /// <summary>
        /// Comma seperated string of denied IPs. Example "10.2.5.41,192.168.0.22"
        /// </summary>
        /// <value></value>
        public string DeniedSingleIPs { get; set; }

        /// <summary>
        /// Comma seperated string of denied IPs with masks. Example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0"
        /// </summary>
        /// <value>The masked I ps.</value>
        public string DeniedMaskedIPs { get; set; }


        /// <summary>
        /// Gets or sets the configuration key for denied single IPs
        /// </summary>
        /// <value>The configuration key single I ps.</value>
        public string ConfigurationKeyDeniedSingleIPs { get; set; }

        /// <summary>
        /// Gets or sets the configuration key for denied masked IPs
        /// </summary>
        /// <value>The configuration key masked I ps.</value>
        public string ConfigurationKeyDeniedMaskedIPs { get; set; }

        /// <summary>
        /// List of denied IPs
        /// </summary>
        IPList deniedIPListToCheck = new IPList();
        #endregion


        /// <summary>
        /// Determines whether access to the core framework is authorized.
        /// </summary>
        /// <param name="actionContext">The HTTP context, which encapsulates all HTTP-specific information about an individual HTTP request.</param>
        /// <returns>
        /// true if access is authorized; otherwise, false.
        /// </returns>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="httpContext"/> parameter is null.</exception>
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            if (actionContext == null)
                throw new ArgumentNullException("actionContext");

            string userIpAddress = ((HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"]).Request.UserHostName;

            try
            {
                // Check that the IP is allowed to access
                bool ipAllowed = CheckAllowedIPs(userIpAddress);

                // Check that the IP is not denied to access
                bool ipDenied = CheckDeniedIPs(userIpAddress);    

                // Only allowed if allowed and not denied
                bool finallyAllowed = ipAllowed && !ipDenied;

                return finallyAllowed;
            }
            catch (Exception e)
            {
                // Log the exception, probably something wrong with the configuration
            }

            return true; // if there was an exception, then we return true
        }

        /// <summary>
        /// Checks the allowed IPs.
        /// </summary>
        /// <param name="userIpAddress">The user ip address.</param>
        /// <returns></returns>
        private bool CheckAllowedIPs(string userIpAddress)
        {
            // Populate the IPList with the Single IPs
            if (!string.IsNullOrEmpty(AllowedSingleIPs))
            {
                SplitAndAddSingleIPs(AllowedSingleIPs, allowedIPListToCheck);
            }

            // Populate the IPList with the Masked IPs
            if (!string.IsNullOrEmpty(AllowedMaskedIPs))
            {
                SplitAndAddMaskedIPs(AllowedMaskedIPs, allowedIPListToCheck);
            }

            // Check if there are more settings from the configuration (Web.config)
            if (!string.IsNullOrEmpty(ConfigurationKeyAllowedSingleIPs))
            {
                string configurationAllowedAdminSingleIPs = ConfigurationManager.AppSettings[ConfigurationKeyAllowedSingleIPs];
                if (!string.IsNullOrEmpty(configurationAllowedAdminSingleIPs))
                {
                    SplitAndAddSingleIPs(configurationAllowedAdminSingleIPs, allowedIPListToCheck);
                }
            }

            if (!string.IsNullOrEmpty(ConfigurationKeyAllowedMaskedIPs))
            {
                string configurationAllowedAdminMaskedIPs = ConfigurationManager.AppSettings[ConfigurationKeyAllowedMaskedIPs];
                if (!string.IsNullOrEmpty(configurationAllowedAdminMaskedIPs))
                {
                    SplitAndAddMaskedIPs(configurationAllowedAdminMaskedIPs, allowedIPListToCheck);
                }
            }

            return allowedIPListToCheck.CheckNumber(userIpAddress);
        }

        /// <summary>
        /// Checks the denied IPs.
        /// </summary>
        /// <param name="userIpAddress">The user ip address.</param>
        /// <returns></returns>
        private bool CheckDeniedIPs(string userIpAddress)
        {
            // Populate the IPList with the Single IPs
            if (!string.IsNullOrEmpty(DeniedSingleIPs))
            {
                SplitAndAddSingleIPs(DeniedSingleIPs, deniedIPListToCheck);
            }

            // Populate the IPList with the Masked IPs
            if (!string.IsNullOrEmpty(DeniedMaskedIPs))
            {
                SplitAndAddMaskedIPs(DeniedMaskedIPs, deniedIPListToCheck);
            }

            // Check if there are more settings from the configuration (Web.config)
            if (!string.IsNullOrEmpty(ConfigurationKeyDeniedSingleIPs))
            {
                string configurationDeniedAdminSingleIPs = ConfigurationManager.AppSettings[ConfigurationKeyDeniedSingleIPs];
                if (!string.IsNullOrEmpty(configurationDeniedAdminSingleIPs))
                {
                    SplitAndAddSingleIPs(configurationDeniedAdminSingleIPs, deniedIPListToCheck);
                }
            }

            if (!string.IsNullOrEmpty(ConfigurationKeyDeniedMaskedIPs))
            {
                string configurationDeniedAdminMaskedIPs = ConfigurationManager.AppSettings[ConfigurationKeyDeniedMaskedIPs];
                if (!string.IsNullOrEmpty(configurationDeniedAdminMaskedIPs))
                {
                    SplitAndAddMaskedIPs(configurationDeniedAdminMaskedIPs, deniedIPListToCheck);
                }
            }

            return deniedIPListToCheck.CheckNumber(userIpAddress);
        }

        /// <summary>
        /// Splits the incoming ip string of the format "IP,IP" example "10.2.0.0,10.3.0.0" and adds the result to the IPList
        /// </summary>
        /// <param name="ips">The ips.</param>
        /// <param name="list">The list.</param>
        private void SplitAndAddSingleIPs(string ips,IPList list)
        {
            var splitSingleIPs = ips.Split(',');
            foreach (string ip in splitSingleIPs)
                list.Add(ip);
        }

        /// <summary>
        /// Splits the incoming ip string of the format "IP;MASK,IP;MASK" example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0" and adds the result to the IPList
        /// </summary>
        /// <param name="ips">The ips.</param>
        /// <param name="list">The list.</param>
        private void SplitAndAddMaskedIPs(string ips, IPList list)
        {
            var splitMaskedIPs = ips.Split(',');
            foreach (string maskedIp in splitMaskedIPs)
            {
                var ipAndMask = maskedIp.Split(';');
                list.Add(ipAndMask[0], ipAndMask[1]); // IP;MASK
            }
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
        }
    }
}

Example usage:

用法示例:

1. Directly specifying the IPs in the code

1.直接在代码中指定IP

    [FilterIP(
         AllowedSingleIPs="10.2.5.55,192.168.2.2",
         AllowedMaskedIPs="10.2.0.0;255.255.0.0,192.168.2.0;255.255.255.0"
    )]
    public class HomeController {
      // Some code here
    }

2. Or, Loading the configuration from the Web.config

2. 或者,从 Web.config 加载配置

    [FilterIP(
         ConfigurationKeyAllowedSingleIPs="AllowedAdminSingleIPs",
         ConfigurationKeyAllowedMaskedIPs="AllowedAdminMaskedIPs",
         ConfigurationKeyDeniedSingleIPs="DeniedAdminSingleIPs",
         ConfigurationKeyDeniedMaskedIPs="DeniedAdminMaskedIPs"
    )]
    public class HomeController {
      // Some code here
    }


<configuration>
<appSettings>
    <add key="AllowedAdminSingleIPs" value="localhost,127.0.0.1"/> <!-- Example "10.2.80.21,192.168.2.2" -->
    <add key="AllowedAdminMaskedIPs" value="10.2.0.0;255.255.0.0"/> <!-- Example "10.2.0.0;255.255.0.0,192.168.2.0;255.255.255.0" -->
    <add key="DeniedAdminSingleIPs" value=""/>    <!-- Example "10.2.80.21,192.168.2.2" -->
    <add key="DeniedAdminMaskedIPs" value=""/>    <!-- Example "10.2.0.0;255.255.0.0,192.168.2.0;255.255.255.0" -->
</appSettings>
</configuration>

回答by tvanfosson

You should have access to the UserHostAddressin the Request object in your controller to do the restriction on. I'd suggest that you may want to extend the AuthorizeAttributeand add your IPaddress restrictions on it so that you can simply decorate any methods or controllers that need this protection.

您应该可以访问UserHostAddress控制器中的 Request 对象来进行限制。我建议您可能想要扩展AuthorizeAttribute并添加您的IP地址限制,以便您可以简单地装饰任何需要这种保护的方法或控制器。

回答by Jorge Rodrigues dos Santos

I needed a solution for this problem in MVC4 that could handle IPv6 and IP ranges. Also, I needed to use white and black-lists for authorization but also use a regular authorization process when the IP was neither.

我需要一个可以处理 IPv6 和 IP 范围的 MVC4 中的这个问题的解决方案。此外,我需要使用白名单和黑名单进行授权,但当 IP 两者都不是时,我也需要使用常规授权流程。

This is the solution I came to after taking a lot from @sabbour and @Richard Szalay(How to check a input IP fall in a specific IP range) awesome posts so I post it back here for whomever it may help.

这是我从@sabbour 和 @Richard Szalay(如何检查输入 IP 落在特定 IP 范围内)中得到很多东西后找到的解决方案,很棒的帖子,所以我把它发回这里给任何可能有帮助的人。

public class MagniAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{

    #region Allowed

    public bool IsPublic { get; set; }
    /// <summary>
    /// Comma seperated string of allowable IPs. Example "10.2.5.41,192.168.0.22"
    /// </summary>
    /// <value></value>        
    public string AllowedSingleIPs { get; set; }

    /// <summary>
    /// Comma seperated string of allowable IPs with masks. Example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0"
    /// </summary>
    /// <value>The masked I ps.</value>
    public string AllowedIPRanges { get; set; }

    /// <summary>
    /// Gets or sets the configuration key for allowed single IPs
    /// </summary>
    /// <value>The configuration key single I ps.</value>
    public string ConfigurationKeyAllowedSingleIPs { get; set; }

    /// <summary>
    /// Gets or sets the configuration key allowed mmasked IPs
    /// </summary>
    /// <value>The configuration key masked I ps.</value>
    public string ConfigurationKeyAllowedMaskedIPs { get; set; }

    #endregion

    #region Denied
    /// <summary>
    /// Comma seperated string of denied IPs. Example "10.2.5.41,192.168.0.22"
    /// </summary>
    /// <value></value>
    public string DeniedSingleIPs { get; set; }

    /// <summary>
    /// Comma seperated string of denied IPs with masks. Example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0"
    /// </summary>
    /// <value>The masked I ps.</value>
    public string DeniedIPRanges { get; set; }


    /// <summary>
    /// Gets or sets the configuration key for denied single IPs
    /// </summary>
    /// <value>The configuration key single I ps.</value>
    public string ConfigurationKeyDeniedSingleIPs { get; set; }

    /// <summary>
    /// Gets or sets the configuration key for denied masked IPs
    /// </summary>
    /// <value>The configuration key masked I ps.</value>
    public string ConfigurationKeyDeniedMaskedIPs { get; set; }

    #endregion


    /// <summary>
    /// Checks the allowed IPs.
    /// </summary>
    /// <param name="userIpAddress">The user ip address.</param>
    /// <returns></returns>
    private bool CheckAllowedIPs(IPAddress userIpAddress)
    {
        List<IPAddress> allowedIPsToCheck = new List<IPAddress>();
        List<IPAddressRange> allowedIPRangesToCheck = new List<IPAddressRange>();

        // Populate the IPList with the Single IPs
        if (!string.IsNullOrEmpty(AllowedSingleIPs))
        {
            SplitAndAddSingleIPs(AllowedSingleIPs, allowedIPsToCheck);
        }

        // Populate the IPList with the Masked IPs
        if (!string.IsNullOrEmpty(AllowedIPRanges))
        {
            SplitAndAddIPRanges(AllowedIPRanges, allowedIPRangesToCheck);
        }

        // Check if there are more settings from the configuration (Web.config)
        if (!string.IsNullOrEmpty(ConfigurationKeyAllowedSingleIPs))
        {
            string configurationAllowedAdminSingleIPs = ConfigurationManager.AppSettings[ConfigurationKeyAllowedSingleIPs];
            if (!string.IsNullOrEmpty(configurationAllowedAdminSingleIPs))
            {
                SplitAndAddSingleIPs(configurationAllowedAdminSingleIPs, allowedIPsToCheck);
            }
        }

        if (!string.IsNullOrEmpty(ConfigurationKeyAllowedMaskedIPs))
        {
            string configurationAllowedAdminMaskedIPs = ConfigurationManager.AppSettings[ConfigurationKeyAllowedMaskedIPs];
            if (!string.IsNullOrEmpty(configurationAllowedAdminMaskedIPs))
            {
                SplitAndAddIPRanges(configurationAllowedAdminMaskedIPs, allowedIPRangesToCheck);
            }
        }

        return allowedIPsToCheck.Any(a => a.Equals(userIpAddress)) || allowedIPRangesToCheck.Any(a => a.IsInRange(userIpAddress));
    }

    /// <summary>
    /// Checks the denied IPs.
    /// </summary>
    /// <param name="userIpAddress">The user ip address.</param>
    /// <returns></returns>
    private bool CheckDeniedIPs(IPAddress userIpAddress)
    {
        List<IPAddress> deniedIPsToCheck = new List<IPAddress>();
        List<IPAddressRange> deniedIPRangesToCheck = new List<IPAddressRange>();

        // Populate the IPList with the Single IPs
        if (!string.IsNullOrEmpty(DeniedSingleIPs))
        {
            SplitAndAddSingleIPs(DeniedSingleIPs, deniedIPsToCheck);
        }

        // Populate the IPList with the Masked IPs
        if (!string.IsNullOrEmpty(DeniedIPRanges))
        {
            SplitAndAddIPRanges(DeniedIPRanges, deniedIPRangesToCheck);
        }

        // Check if there are more settings from the configuration (Web.config)
        if (!string.IsNullOrEmpty(ConfigurationKeyDeniedSingleIPs))
        {
            string configurationDeniedAdminSingleIPs = ConfigurationManager.AppSettings[ConfigurationKeyDeniedSingleIPs];
            if (!string.IsNullOrEmpty(configurationDeniedAdminSingleIPs))
            {
                SplitAndAddSingleIPs(configurationDeniedAdminSingleIPs, deniedIPsToCheck);
            }
        }

        if (!string.IsNullOrEmpty(ConfigurationKeyDeniedMaskedIPs))
        {
            string configurationDeniedAdminMaskedIPs = ConfigurationManager.AppSettings[ConfigurationKeyDeniedMaskedIPs];
            if (!string.IsNullOrEmpty(configurationDeniedAdminMaskedIPs))
            {
                SplitAndAddIPRanges(configurationDeniedAdminMaskedIPs, deniedIPRangesToCheck);
            }
        }

        return deniedIPsToCheck.Any(a => a.Equals(userIpAddress)) || deniedIPRangesToCheck.Any(a => a.IsInRange(userIpAddress));
    }

    /// <summary>
    /// Splits the incoming ip string of the format "IP,IP" example "10.2.0.0,10.3.0.0" and adds the result to the IPAddress list
    /// </summary>
    /// <param name="ips">The ips.</param>
    /// <param name="list">The list.</param>
    private void SplitAndAddSingleIPs(string ips, List<IPAddress> list)
    {
        var splitSingleIPs = ips.Split(',');
        IPAddress ip;

        foreach (string ipString in splitSingleIPs)
        {
            if(IPAddress.TryParse(ipString, out ip))
                list.Add(ip);
        }
    }

    /// <summary>
    /// Splits the incoming ip ranges string of the format "IP-IP,IP-IP" example "10.2.0.0-10.2.255.255,10.3.0.0-10.3.255.255" and adds the result to the IPAddressRange list
    /// </summary>
    /// <param name="ips">The ips.</param>
    /// <param name="list">The list.</param>
    private void SplitAndAddIPRanges(string ips, List<IPAddressRange> list)
    {
        var splitMaskedIPs = ips.Split(',');
        IPAddress lowerIp;
        IPAddress upperIp;
        foreach (string maskedIp in splitMaskedIPs)
        {
            var ipRange = maskedIp.Split('-');
            if (IPAddress.TryParse(ipRange[0], out lowerIp) && IPAddress.TryParse(ipRange[1], out upperIp))
                list.Add(new IPAddressRange(lowerIp, upperIp));
        }
    }

    protected void HandleUnauthorizedRequest(AuthorizationContext context)
    {
        context.Result = new RedirectToRouteResult(new RouteValueDictionary { { "Controller", "Home" },
                                                                                    { "Action", "Login" },
                                                                                    { "OriginalURL", context.HttpContext.Request.Url.AbsoluteUri } });
    }

    protected bool AuthorizeCore(AuthorizationContext context)
    {
        try
        {
            string userIPString = context.HttpContext.Request.UserHostName;
            IPAddress userIPAddress = IPAddress.Parse(userIPString);

            // Check that the IP is allowed to access
            bool? ipAllowed = CheckAllowedIPs(userIPAddress) ? true : (bool?)null;

            // Check that the IP is not denied to access
            ipAllowed = CheckDeniedIPs(userIPAddress) ? false : ipAllowed;

            if (ipAllowed.HasValue)
            {
                return ipAllowed.Value;
            }

            var serverSession = context.HttpContext.Session;

            UserSession session = null;

            //usersession in server session
            if (serverSession[Settings.HttpContextUserSession] != null)
            {
                session = (UserSession)serverSession[Settings.HttpContextUserSession];
                Trace.TraceInformation($"[{MethodBase.GetCurrentMethod().Name}] UserId:" + session.UserId + ". ClientId: " + session.ClientId);
                return true;
            }

            //usersession in database from cookie
            session = UserSession.GetSession(context.HttpContext.Request.Cookies.Get("sessionId").Value);
            if (session != null)
            {
                Trace.TraceInformation($"[{MethodBase.GetCurrentMethod().Name}] Session found for cookie {context.HttpContext.Request.Cookies.Get("sessionId").Value}");
                serverSession[Settings.HttpContextUserSession] = session;
                Trace.TraceInformation($"[{MethodBase.GetCurrentMethod().Name}] UserId:" + session.UserId + ". ClientId: " + session.ClientId);

                return true;
            }
            else
            {
                Trace.TraceInformation($"[{MethodBase.GetCurrentMethod().Name}] No session found for cookie {serverSession["cookie"]}");
                return false;
            }

        }
        catch (Exception ex)
        {
            Trace.TraceError($"[{MethodBase.GetCurrentMethod().Name}] exception: {ex.Message} - trace {ex.StackTrace}");
            return false;
        }
    }

    public void OnAuthorization(AuthorizationContext actionContext)
    {
        if (IsPublic == false && AuthorizeCore(actionContext) == false)
        {
            HandleUnauthorizedRequest(actionContext);
        }
    }
}

回答by bgx

I found sabbour's solution excellent but needed to make two changes to be more useful for my purposes:

我发现 sabbour 的解决方案非常好,但需要进行两项更改才能对我的目的更有用:

  1. Allow access if the allowed list is empty. This way you can allow any IP by simply changing the config (e.g. for test deployments) or allow all IPs except explicitly denied ones. To do this I extended IPList to include a Count property and check it as part of CheckAllowedIPs:

    return _allowedIpListToCheck.Count == 0 || _allowedIpListToCheck.CheckNumber(userIpAddress);
    
  2. Override HandleUnauthorizedRequest to always return 403. The AuthorizeAtrribute returns 401 by default:

    public override void OnAuthorization(AuthorizationContext actionContext)
    {
        if (AuthorizeCore((HttpContextBase)actionContext.HttpContext))
            return;
        HandleUnauthorizedRequest(actionContext);
    }
    
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
            filterContext.Result = new HttpStatusCodeResult(403, "IP Access Denied");
    }
    
  1. 如果允许列表为空,则允许访问。通过这种方式,您可以通过简单地更改配置(例如用于测试部署)来允许任何 IP,或者允许除明确拒绝的 IP 之外的所有 IP。为此,我扩展了 IPList 以包含一个 Count 属性并将其作为 CheckAllowedIPs 的一部分进行检查:

    return _allowedIpListToCheck.Count == 0 || _allowedIpListToCheck.CheckNumber(userIpAddress);
    
  2. 覆盖 HandleUnauthorizedRequest 以始终​​返回 403。 AuthorizeAtrribute 默认返回 401:

    public override void OnAuthorization(AuthorizationContext actionContext)
    {
        if (AuthorizeCore((HttpContextBase)actionContext.HttpContext))
            return;
        HandleUnauthorizedRequest(actionContext);
    }
    
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
            filterContext.Result = new HttpStatusCodeResult(403, "IP Access Denied");
    }
    

Here is the full variation of the FilterIpAttribute class:

这是 FilterIpAttribute 类的完整变体:

public class FilterIpAttribute:AuthorizeAttribute
{

    #region Allowed
    /// <summary>
    /// Comma seperated string of allowable IPs. Example "10.2.5.41,192.168.0.22"
    /// </summary>
    /// <value></value>
    public string AllowedSingleIPs { get; set; }

    /// <summary>
    /// Comma seperated string of allowable IPs with masks. Example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0"
    /// </summary>
    /// <value>The masked I ps.</value>
    public string AllowedMaskedIPs { get; set; }

    /// <summary>
    /// Gets or sets the configuration key for allowed single IPs
    /// </summary>
    /// <value>The configuration key single I ps.</value>
    public string ConfigurationKeyAllowedSingleIPs { get; set; }

    /// <summary>
    /// Gets or sets the configuration key allowed mmasked IPs
    /// </summary>
    /// <value>The configuration key masked I ps.</value>
    public string ConfigurationKeyAllowedMaskedIPs { get; set; }

    /// <summary>
    /// List of allowed IPs
    /// </summary>
    readonly IpList _allowedIpListToCheck = new IpList();
    #endregion

    #region Denied
    /// <summary>
    /// Comma seperated string of denied IPs. Example "10.2.5.41,192.168.0.22"
    /// </summary>
    /// <value></value>
    public string DeniedSingleIPs { get; set; }

    /// <summary>
    /// Comma seperated string of denied IPs with masks. Example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0"
    /// </summary>
    /// <value>The masked I ps.</value>
    public string DeniedMaskedIPs { get; set; }


    /// <summary>
    /// Gets or sets the configuration key for denied single IPs
    /// </summary>
    /// <value>The configuration key single I ps.</value>
    public string ConfigurationKeyDeniedSingleIPs { get; set; }

    /// <summary>
    /// Gets or sets the configuration key for denied masked IPs
    /// </summary>
    /// <value>The configuration key masked I ps.</value>
    public string ConfigurationKeyDeniedMaskedIPs { get; set; }

    /// <summary>
    /// List of denied IPs
    /// </summary>
    readonly IpList _deniedIpListToCheck = new IpList();
    #endregion

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException("httpContext");

        string userIpAddress = httpContext.Request.UserIp();

        try
        {
            // Check that the IP is allowed to access
            bool ipAllowed = CheckAllowedIPs(userIpAddress);

            // Check that the IP is not denied to access
            bool ipDenied = CheckDeniedIPs(userIpAddress);

            //Only allowed if allowed and not denied

            bool finallyAllowed = ipAllowed && !ipDenied;


            return finallyAllowed;
        }
        catch (Exception e)
        {
            // Log the exception, probably something wrong with the configuration
        }

        return true; // if there was an exception, then we return true
    }

    /// <summary>
    /// Checks the allowed IPs.
    /// </summary>
    /// <param name="userIpAddress">The user ip address.</param>
    /// <returns></returns>
    private bool CheckAllowedIPs(string userIpAddress)
    {
        // Populate the IPList with the Single IPs
        if (!string.IsNullOrEmpty(AllowedSingleIPs))
        {
            SplitAndAddSingleIPs(AllowedSingleIPs, _allowedIpListToCheck);
        }

        // Populate the IPList with the Masked IPs
        if (!string.IsNullOrEmpty(AllowedMaskedIPs))
        {
            SplitAndAddMaskedIPs(AllowedMaskedIPs, _allowedIpListToCheck);
        }

        // Check if there are more settings from the configuration (Web.config)
        if (!string.IsNullOrEmpty(ConfigurationKeyAllowedSingleIPs))
        {
            string configurationAllowedAdminSingleIPs = ConfigurationManager.AppSettings[ConfigurationKeyAllowedSingleIPs];
            if (!string.IsNullOrEmpty(configurationAllowedAdminSingleIPs))
            {
                SplitAndAddSingleIPs(configurationAllowedAdminSingleIPs, _allowedIpListToCheck);
            }
        }

        if (!string.IsNullOrEmpty(ConfigurationKeyAllowedMaskedIPs))
        {
            string configurationAllowedAdminMaskedIPs = ConfigurationManager.AppSettings[ConfigurationKeyAllowedMaskedIPs];
            if (!string.IsNullOrEmpty(configurationAllowedAdminMaskedIPs))
            {
                SplitAndAddMaskedIPs(configurationAllowedAdminMaskedIPs, _allowedIpListToCheck);
            }
        }

        return _allowedIpListToCheck.Count == 0 || _allowedIpListToCheck.CheckNumber(userIpAddress);
    }

    /// <summary>
    /// Checks the denied IPs.
    /// </summary>
    /// <param name="userIpAddress">The user ip address.</param>
    /// <returns></returns>
    private bool CheckDeniedIPs(string userIpAddress)
    {
        // Populate the IPList with the Single IPs
        if (!string.IsNullOrEmpty(DeniedSingleIPs))
        {
            SplitAndAddSingleIPs(DeniedSingleIPs, _deniedIpListToCheck);
        }

        // Populate the IPList with the Masked IPs
        if (!string.IsNullOrEmpty(DeniedMaskedIPs))
        {
            SplitAndAddMaskedIPs(DeniedMaskedIPs, _deniedIpListToCheck);
        }

        // Check if there are more settings from the configuration (Web.config)
        if (!string.IsNullOrEmpty(ConfigurationKeyDeniedSingleIPs))
        {
            string configurationDeniedAdminSingleIPs = ConfigurationManager.AppSettings[ConfigurationKeyDeniedSingleIPs];
            if (!string.IsNullOrEmpty(configurationDeniedAdminSingleIPs))
            {
                SplitAndAddSingleIPs(configurationDeniedAdminSingleIPs, _deniedIpListToCheck);
            }
        }

        if (!string.IsNullOrEmpty(ConfigurationKeyDeniedMaskedIPs))
        {
            string configurationDeniedAdminMaskedIPs = ConfigurationManager.AppSettings[ConfigurationKeyDeniedMaskedIPs];
            if (!string.IsNullOrEmpty(configurationDeniedAdminMaskedIPs))
            {
                SplitAndAddMaskedIPs(configurationDeniedAdminMaskedIPs, _deniedIpListToCheck);
            }
        }

        return _deniedIpListToCheck.CheckNumber(userIpAddress);
    }

    /// <summary>
    /// Splits the incoming ip string of the format "IP,IP" example "10.2.0.0,10.3.0.0" and adds the result to the IPList
    /// </summary>
    /// <param name="ips">The ips.</param>
    /// <param name="list">The list.</param>
    private void SplitAndAddSingleIPs(string ips, IpList list)
    {
        var splitSingleIPs = ips.Split(',');
        foreach (string ip in splitSingleIPs)
            list.Add(ip);
    }

    /// <summary>
    /// Splits the incoming ip string of the format "IP;MASK,IP;MASK" example "10.2.0.0;255.255.0.0,10.3.0.0;255.255.0.0" and adds the result to the IPList
    /// </summary>
    /// <param name="ips">The ips.</param>
    /// <param name="list">The list.</param>
    private void SplitAndAddMaskedIPs(string ips, IpList list)
    {
        var splitMaskedIPs = ips.Split(',');
        foreach (string maskedIp in splitMaskedIPs)
        {
            var ipAndMask = maskedIp.Split(';');
            list.Add(ipAndMask[0], ipAndMask[1]); // IP;MASK
        }
    }

    public override void OnAuthorization(AuthorizationContext actionContext)
    {
        if (AuthorizeCore((HttpContextBase)actionContext.HttpContext))
            return;
        HandleUnauthorizedRequest(actionContext);
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
            filterContext.Result = new HttpStatusCodeResult(403, "IP Access Denied");
    }
}

An extension method to get the User IP as suggested by osa on github

获取用户 IP 的扩展方法,如 osa 在github上的建议

public static class HttpUtils {

    public static string UserIp(this HttpRequestBase request)
    {
        var ip = request["HTTP_X_FORWARDED_FOR"];

        if (!string.IsNullOrWhiteSpace(ip))
        {
            ip = ip.Split(',').Last().Trim();
        }

        if (string.IsNullOrWhiteSpace(ip))
        {
            ip = request.UserHostAddress;
        }

        return ip;
    }
}

And finally the IPList modification (full source is here) :

最后是 IPList 修改(完整源代码在这里):

internal class IpArrayList
{
    //[...]
    public int Count
    {
        get { return _ipNumList.Count; }
    }

 }

public class IpList
{
      //[...]
     public int Count
     {
         get { return _usedList.Count; }
     }
}

回答by HO3EiN

Simplest way that im using

我使用的最简单的方法

first:

第一的:

add one row on config table (if you have) or any other table and insert your accessible IPs to this table.

在配置表(如果有)或任何其他表上添加一行,并将您的可访问 IP 插入该表。

second:

第二:

add this action filter to your startup.cs

将此操作过滤器添加到您的 startup.cs

public class IpAuthAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
        string ip = System.Web.HttpContext.Current.Request.UserHostAddress;
        string ips = "";
        using (var db = new DataBase())
        {
            ips = db.Configs.SingleOrDefault().IP;
        }
        if (!ips.Contains(ip))
        {
            filterContext.Result = new RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary(new
            {
                controller = "Account",
                action = "OutOfRange"
            }));
        }
    }
}

then use this on every action you want on your controllers

然后在控制器上的每个操作上使用它

[IpAuth]
public ActionResult Index()
{
    return View();
}