自定义AuthorizeFilter:如何添加过滤器以检查客户端IP或授权给IdentityServer

时间:2019-06-07 09:08:31

标签: c# authorization identityserver4 asp.net-core-webapi authorize-attribute

我正在开发一个Net Core 2.2 Web API。 我具有通过Identityserver进行的安装授权,并且工作正常。 现在,喜欢将api置于azure api管理之后,并喜欢将api管理ip地址添加到白名单中,因此,如果请求来自api管理,则不会通过Identityserver授权。

我想做的是添加一个自定义的授权过滤器,检查客户端ip,如果ip有效,我将不通过Identityserver进行授权,但是如果ip无效,我将尝试进行授权通过身份服务器。

我想覆盖此AuthorizeFilter。有人有提示吗?

services.AddMvc(options =>
{
    if (!_env.IsUnitTest())
    {
        //Add global filter to make sure we require authenticated users for everything!
       var requireAuthenticatedUsersPolicy =
           new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
       options.Filters.Add(new AuthorizeFilter(requireAuthenticatedUsersPolicy));
    }
});

2 个答案:

答案 0 :(得分:1)

您可以使用“操作”过滤器来检查特定控制器或操作方法的请求的远程IP地址。整个代码示例位于this article中:

public class ClientIdCheckFilter : ActionFilterAttribute
{
    private readonly ILogger _logger;
    private readonly string _safelist;

    public ClientIdCheckFilter
        (ILoggerFactory loggerFactory, IConfiguration configuration)
    {
        _logger = loggerFactory.CreateLogger("ClientIdCheckFilter");
        _safelist = configuration["AdminSafeList"];
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        _logger.LogInformation(
            $"Remote IpAddress: {context.HttpContext.Connection.RemoteIpAddress}");

        var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
        _logger.LogDebug($"Request from Remote IP address: {remoteIp}");

        string[] ip = _safelist.Split(';');

        var bytes = remoteIp.GetAddressBytes();
        var badIp = true;
        foreach (var address in ip)
        {
            var testIp = IPAddress.Parse(address);
            if (testIp.GetAddressBytes().SequenceEqual(bytes))
            {
                badIp = false;
                break;
            }
        }

        if (badIp)
        {
            _logger.LogInformation(
                $"Forbidden Request from Remote IP address: {remoteIp}");
            context.Result = new StatusCodeResult(401);
            return;
        }

        base.OnActionExecuting(context);
    }
}

答案 1 :(得分:1)

谢谢! 我通过添加需求和处理程序来完成此工作:

public class IpAddressWhitelistHandler : AuthorizationHandler<IpAddressWhitelistRequirement>
{
    private readonly IHttpContextAccessor _httpAccessor;

    public IpAddressWhitelistHandler(IHttpContextAccessor httpAccessor)
    {
        _httpAccessor = httpAccessor;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IpAddressWhitelistRequirement requirement)
    {
        var remoteIp = _httpAccessor.HttpContext.Connection.RemoteIpAddress;
        if (IsIpValid(remoteIp, requirement))
        {
            context.Succeed(requirement);
        }

        else
        {
            if (IsAuthenticated(context.User))
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }

        return Task.CompletedTask;

    }

    private bool IsIpValid(IPAddress ipAddress, IpAddressWhitelistRequirement requirement)
    {
        bool validIp = false;

        var bytes = ipAddress.GetAddressBytes();

        var safeIp = IPAddress.Parse(requirement.IpAddress);
        if (safeIp.GetAddressBytes().SequenceEqual(bytes))
        {
            validIp = true;
        }

        return validIp;
    }

    private bool IsAuthenticated(ClaimsPrincipal user)
    {
        var userIsAnonymous = user?.Identity == null || !user.Identities.Any(i => i.IsAuthenticated);

        return !userIsAnonymous;

    }
}

public class IpAddressWhitelistRequirement : IAuthorizationRequirement
{
    public string IpAddress { get; set; }
}