根据客户端IP地址授权应用程序服务

时间:2018-02-03 12:24:31

标签: c# authorization ip-address interceptor aspnetboilerplate

我们在未经许可的情况下实施了一些应用服务方法。我们如何实现基于客户端IP地址的授权来执行方法?

例如,这是GetParsedData方法:

public GetParsedDataOutput GetParsedData(GetParsedDataInput input)
{
    return _cacheManager.GetCache(nameof(GetData)).Get(input.ToString(), () => gpd(input)) as GetParsedDataOutput;
}

我们如何通过IP地址检查用户权限?假设IP地址为192.168.5.2的客户端被授予执行此方法的权限。

2 个答案:

答案 0 :(得分:5)

您可以注入IClientInfoProvider来获取ClientIpAddress

授权经过身份验证的用户

覆盖PermissionChecker中的IsGrantedAsync

public override async Task<bool> IsGrantedAsync(long userId, string permissionName)
{
    if (permissionName == MyClientIpAddressPermissionName)
    {
        return Task.Run(() => { return _clientInfoProvider.ClientIpAddress == "192.168.5.2"; });
    }

    return await base.IsGrantedAsync(userId, permissionName);
}

用法:

[AbpAuthorize(MyClientIpAddressPermissionName)]
public GetParsedDataOutput GetParsedData(GetParsedDataInput input)
{
    // ...
}

授权匿名用户

由于AbpAuthorize需要用户,因此您应该使用自定义(i)属性,(ii)拦截器,以及(iii)拦截器注册器。

(i)属性:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ClientIpAuthorizeAttribute : Attribute
{
    public string AllowedIpAddress { get; set; }
}

(ii)拦截器:

internal class ClientIpAuthorizationInterceptor : IInterceptor
{
    private readonly IClientInfoProvider _clientInfoProvider;

    public ClientIpAuthorizationInterceptor(IClientInfoProvider clientInfoProvider)
    {
        _clientInfoProvider = clientInfoProvider;
    }

    public void Intercept(IInvocation invocation)
    {
        var methodInfo = invocation.MethodInvocationTarget;
        var clientIpAuthorizeAttribute = methodInfo.GetCustomAttributes(true).OfType<ClientIpAuthorizeAttribute>().FirstOrDefault()
                        ?? methodInfo.DeclaringType.GetCustomAttributes(true).OfType<ClientIpAuthorizeAttribute>().FirstOrDefault();

        if (clientIpAuthorizeAttribute != null &&
            clientIpAuthorizeAttribute.AllowedIpAddress != _clientInfoProvider.ClientIpAddress)
        {
            throw new AbpAuthorizationException();
        }

        invocation.Proceed();
    }
}

(iii)拦截器注册员:

internal static class ClientIpAuthorizationInterceptorRegistrar
{
    public static void Initialize(IIocManager iocManager)
    {
        iocManager.IocContainer.Kernel.ComponentRegistered += (key, handler) =>
        {
            if (ShouldIntercept(handler.ComponentModel.Implementation))
            {
                handler.ComponentModel.Interceptors.Add(new InterceptorReference(typeof(ClientIpAuthorizationInterceptor)));
            }
        };
    }

    private static bool ShouldIntercept(Type type)
    {
        if (type.GetTypeInfo().IsDefined(typeof(ClientIpAuthorizeAttribute), true))
        {
            return true;
        }

        if (type.GetMethods().Any(m => m.IsDefined(typeof(ClientIpAuthorizeAttribute), true)))
        {
            return true;
        }

        return false;
    }
}

在您的应用程序模块中初始化注册商:

public override void PreInitialize()
{
    ClientIpAuthorizationInterceptorRegistrar.Initialize(IocManager);
}

用法:

[ClientIpAuthorize(AllowedIpAddress = "192.168.5.2")]
public GetParsedDataOutput GetParsedData(GetParsedDataInput input)
{
    // ...
}

您应该能够自己扩展它以允许/禁止多个IP地址。

要回退经过身份验证的用户的权限名称,请在属性中将权限名称添加为string属性。然后在拦截器中注入IAbpSessionIPermissionChecker以调用IsGrantedAsync方法。

答案 1 :(得分:0)

您可以为IApplicationService编写自己的注入服务。在应用程序服务方法执行之前,您可以进行预检查。

了解如何实施注射 https://aspnetboilerplate.com/Pages/Documents/Dependency-Injection