属性和自定义属性-授权如何工作?

时间:2019-12-13 19:26:00

标签: c# attributes custom-attributes

我正在尝试模拟[Authorize]属性,因为我发现您可以将属性放在整个类的顶部而感到惊讶,并且这样做会以某种方式阻止所有人在类中运行方法除非...某事...

我查找了创建自定义属性的信息,并找到了一些答案,这些回答基本上说,除非我们使用反射,否则属性不可能阻止方法的调用,因此我决定深入研究Authorize属性,但只能找到“接口”方法,基本上就这样

[Authorize]属性到底在做什么?如何使用反射实现属性来实际执行操作?例如。归于一个类时,以下内容不起作用:

[System.AttributeUsage(System.AttributeTargets.Class)]
public class Authorise : System.Attribute
{
    public Authorise()
    {
        if (!SomeBoolCondition) throw new Exception ("Oh no!");
    }
}

我无法理解Authorize属性如何进行检查,然后将程序重定向到登录页面。

1 个答案:

答案 0 :(得分:1)

如果您想使用自定义属性实现自己的授权逻辑,则还需要在请求管道中创建并注册middleware。您的中间件将收到整个HttpContext,您可以使用它来通过其元数据检查端点的CustomAuthorizeAttribute。在这里,您可以实现授权逻辑,并决定通过“ await next.Invoke()”继续在管道中处理请求,或者停止处理并将未经授权的响应返回给客户端。

属性类:

[AttributeUsage(AttributeTargets.Class)]
public class CustomAuthorizeAttribute : Attribute
{
    public IEnumerable<string> AllowedUserRoles { get; private set; }

    public CustomAuthorizeAttribute(params string[] allowedUserRoles)
    {
        this.AllowedUserRoles = allowedUserRoles.AsEnumerable();
    }
}

具有自定义属性的控制器:

[ApiController]
[Route("[controller]")]
[CustomAuthorize("Admin", "Supervisor", "Worker")]
public class WeatherForecastController : ControllerBase
{
}

启动。使用自定义中间件进行配置:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.Use(async (httpContext, next) =>
    {
        var endpointMetaData = httpContext.GetEndpoint()
            .Metadata;

        bool hasCustomAuthorizeAttribute = endpointMetaData.Any(x => x is CustomAuthorizeAttribute);

        if (hasCustomAuthorizeAttribute)
        {
            // get the endpoint's instance of CustomAuthorizeAttribute
            CustomAuthorizeAttribute customAuthorieAttribute = endpointMetaData
                .FirstOrDefault(x => x is CustomAuthorizeAttribute) as CustomAuthorizeAttribute;

            // here you will have access to customAuthorizeAttribute.AllowedUserRoles
            // and can execute your custom logic with it
            bool isAuthorized = true;

            if (isAuthorized)
            {
                // continue processing the request
                await next.Invoke();
            }
            else
            {
                // stop processing request and return unauthorized response
                httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                await httpContext.Response.WriteAsync("Unauthorized");
            }
        }
    });

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}