在Web API中创建自定义AuthorizeAttribute(.Net Framework)

Jay*_*ran 10 c# authorize-attribute oauth-2.0 asp.net-web-api2

我在我的WebAPI中使用OAuth2.0 Owin(密码授权).我的初始令牌响应如下所示

{
    "access_token": "_ramSlQYasdsRTWEWew.....................",
    "token_type": "bearer",
    "expires_in": 17999,
    "permissions": {
        "user": [
            "Add",
            "Update",
            "Delete"
        ],
        "Product": [
            "Read",
            "Create"
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

我通过创建一个名为" 持有相应用户权限" 的新密钥来自定义响应permissions.

从这里我需要Resource server通过检查用户是否具有使用授权属性调用API的足够权限来验证来自我的每个请求.

我在这里找到了一个类似的例子,它涉及Dot net Core,这不适合我的情况.

困难的部分是permissionJSON Key本身就是一个复杂的ArrayList

[CustomAuthorize(PermissionItem.Product, PermissionAction.Read)]
    public async Task<IActionResult> Index()
    {
        return View(Index);
    }

public class CustomAuthorize : AuthorizeAttribute {
    public AuthorizeAttribute (PermissionItem item, PermissionAction action) {
        //Need to initalize the Permission Enums
    }
    public override void OnAuthorization (HttpActionContext actionContext) {
        //Code to get the value from Permissions ArrayList and compare it with the Enum values
    }
}
Run Code Online (Sandbox Code Playgroud)

以上是我的想法.但由于PermissionsKey和Enum比较的复杂性,我无法继续前进.

此外,还有一个问题,如果用户的权限是添加以及更新意味着我需要在我的控制器之前创建两个属性条件.

喜欢

[CustomAuthorize(PermissionItem.User, PermissionAction.Add)]
[CustomAuthorize(PermissionItem.User, PermissionAction.Update)]
Run Code Online (Sandbox Code Playgroud)

这导致添加更多的属性行.那么有没有办法让它像单独的条件一样|分开?

[CustomAuthorize(PermissionItem.User, PermissionAction.Update|PermissionAction.Add)]
Run Code Online (Sandbox Code Playgroud)

Dip*_*hah 6

为什么不允许您的 CustomAuthorize 构造函数具有多个 Permission 操作。

public class CustomAuthorize : AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
        if (!currentIdentity.IsAuthenticated) {
            // redirect to access denied page
        }

        var userName = currentIdentity.Name;
        // step 1 : retrieve user object

        // step 2 : retrieve user permissions

        // step 3 : match user permission(s) agains class/method's required premissions

        // step 4 : continue/redirect to access denied page
    }
}
Run Code Online (Sandbox Code Playgroud)

您将使用以下内容注释您的课程: [CustomAuthorize(PermissionItem.User, PermissionAction.Update, PermissionAction.Add)]

我不确定,OP 想在这里实现什么。如果您依赖 HTTP 请求来提供访问权限,那么这是一个很大的安全漏洞。对于每个请求,您应该从数据库中检索用户的访问权限信息,然后根据类/方法所需的权限进行匹配。

根据经验,您不应该依赖请求对象来告诉您当前用户拥有哪些权限。您应该从数据存储中检索它们。

我对 CustomAttribute 的实现

public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    protected override Boolean IsAuthorized(HttpActionContext actionContext)
    {
        var currentIdentity = actionContext.RequestContext.Principal.Identity;
        if (!currentIdentity.IsAuthenticated)
            return false;

        var userName = currentIdentity.Name;
        using (var context = new DataContext())
        {
            var userStore = new UserStore<AppUser>(context);
            var userManager = new UserManager<AppUser>(userStore);
            var user = userManager.FindByName(userName);

            if (user == null)
                return false;

            foreach (var role in permissionActions)
                if (!userManager.IsInRole(user.Id, Convert.ToString(role)))
                    return false;

            return true;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)