本文介绍了扩展授权属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基于[Authorize]属性实现了[CustomAuthorization]属性.我的属性如下:

I'm implemented a [CustomAuthorization] attribute based on [Authorize] attribute. My attribute looks like this:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public eUserRole CustomRoles { get; set; } = eUserRole.Administrator; // If not specified, the required role is Administrator

    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        AuthorizationSystem auth = new AuthorizationSystem(actionContext.RequestContext.Principal, this.CopyleaksRoles);
        var res = auth.Validate();
        if (!res)
            return false;

        return base.IsAuthorized(actionContext);
    }
}

我将逻辑(谁接受和谁不接受)划分为单独的课程.如果根据其CustomRoles属性接受了用户,则方法AuthorizationSystem.Validate()返回true.

I splitted the logic (who to accept and who not) to seperated class. The method AuthorizationSystem.Validate() return true if the user is accepted according to his CustomRoles property.

我的控制器看起来像:

[CustomAuthorize]
public class MyController : ApiController
{
    [CustomAuthorize(CustomRoles = eUserRole.Readonly)]
    public Response Do()
    {
        // ... Do something ...
    }
}

我正在运行应用程序(C#+ WebAPI),以检查其是否正常运行.

I'm running the application (C# + WebAPI) to check if it working.

我调试了代码,看到第一次运行时,最低要求的角色级别是Administrator而不是Readonly.因为当使用不带任何CustomRoles[CustomAuthorize]时,它会将默认行定义为eUserRole.Administrator.这意味着被调用的第一个CustomAuthorize属性是类级别的属性,不是方法级别的.

I debugging the code and see that on the first run the minimum required role level is Administrator instead of Readonly. Because when using [CustomAuthorize] without any CustomRoles, it's define the default row to be eUserRole.Administrator. That mean that the first CustomAuthorize attribute that being called is the attribute on class level, not on method level.

如何使其调用方法(Do())之前的属性?

How to make it call the attribute that on the method (Do()) before?

推荐答案

您对AuthorizeAttribute同时实现AttributeIAuthorizationFilter的事实感到困惑.您需要做的是在全局范围内注册IAuthorizationFilter,并使用它来确定CustomAuthorizeAttribute在操作或控制器上是否存在.然后,您可以确定哪个优先于另一个.

You are getting confused by the fact that AuthorizeAttribute implements both Attribute and IAuthorizationFilter. What you need to do is make a globally registered IAuthorizationFilter and use it to determine whether the CustomAuthorizeAttribute exists on the action or controller. Then you can determine which takes precedence over the other.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustomAuthorizeAttribute : Attribute
{
    public eUserRole CustomRoles { get; set; } = eUserRole.Administrator;
}

CustomAuthoizationFilter

这里我们通过子类化AuthorizeAttribute节省了一些步骤,但是我们根本不打算将它作为Attribute,而只是一个全局注册的过滤器.

CustomAuthoizationFilter

Here we save some steps by subclassing AuthorizeAttribute, but we don't intend for this to be an Attribute at all, only a globally registered filter.

我们的过滤器包含反射代码,以确定如果同时定义了两个CustomAuthorize属性,该属性优先.设置该方法是为了使操作方法优先于控制器,但是如果需要,您可以使逻辑更复杂.

Our filter contains Reflection code to determine which CustomAuthorize attribute takes precedence if both are defined. This is setup to make the action method override the controller, but you can make the logic more complex, if needed.

public class CustomAuthorizationFilter : AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        if (base.IsAuthorized(actionContext))
        {
            var authorizeAttribute = GetAuthorizeAttribute(actionContext.ActionDescriptor);

            // Attribute doesn't exist - return true
            if (authorizeAttribute == null)
                return true;

            var roles = authorizeAttribute.CustomRoles;

            // Logic - return true if authorized, false if not authorized

        }

        return false;
    }

    private CustomAuthorizeAttribute GetAuthorizeAttribute(HttpActionDescriptor actionDescriptor)
    {
        // Check action level
        CustomAuthorizeAttribute result = actionDescriptor
            .GetCustomAttributes<CustomAuthorizeAttribute>()
            .FirstOrDefault();

        if (result != null)
            return result;

        // Check class level
        result = actionDescriptor
            .ControllerDescriptor
            .GetCustomAttributes<CustomAuthorizeAttribute>()
            .FirstOrDefault();

        return result;
    }
}

用法

我们在全局注册过滤器.对于每个请求,CustomAuthorizationFilter都会扫描请求中的操作和控制器,以查看该属性是否存在.如果是这样,它将运行逻辑.

Usage

We register the filter globally. For each request, CustomAuthorizationFilter scans the action and controller in the request to see if the attribute exists. If so, it then runs the logic.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

        // Register our Custom Authorization Filter
        config.Filters.Add(new CustomAuthorizationFilter());

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

参考:被动属性

这篇关于扩展授权属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 22:26