ASP.NET WebAPI动态授权 [英] asp.net webapi dynamic authorization

查看:129
本文介绍了ASP.NET WebAPI动态授权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是webapi和mvc的新手,我正在努力寻找最佳实践,以便根据资源的角色和所有权动态处理授权。例如,一个帐户页面应允许员工管理员,员工呼叫中心或拥有客户的客户端获取,发布,放置或删除帐户信息。因此,管理员和呼叫中心的员工应该能够获取,发布,放置或删除对任何用户ID的任何请求,但是客户端只能对他们拥有的资源执行这些操作。

I am new to webapi and mvc and I am struggling to find a best practice for handling authorizations dynamically based on roles and ownership of the resource. For example an account page that should allow employee admins, employee call center or the owning client to Get, Post, Put or Delete account information. So an admin and call center employee should be able to Get, Post, Put or Delete any request for any userid, but a client should only be able to perform these actions on resources owned by them.

例如Tom是UserID 10,而Jerry是UserID 20。

For example Tom is UserID 10 and Jerry is UserID 20.

/ api / Account / 10应该可由任何管理员,呼叫中心或Tom访问。杰里应该被踢出去。
/ api / Account / 20应该可由任何管理员,呼叫中心或Jerry访问。

/api/Account/10 should be accessible by any admin, call center or Tom. Jerry should be kicked out. /api/Account/20 should be accessible by any admin, call center or Jerry. Tom should be kicked out.

在webforms中,典型的解决方案是只检查用户是否是客户端,并根据请求验证其ID。 (我知道AuthorizeAttribute不在webforms中,而是在webapi / mvc中作为其隐蔽内容的示例。)

In webforms the typical solution is to just check if the user is a client and verify their id against the request. (I know AuthorizeAttribute is not in webforms, but showing as an example of what it would covert to in webapi/mvc.)

    [Authorize(Roles = "Administrator, CallCenter, Client")]
    public string Get(int userID)
    {
        if (Thread.CurrentPrincipal.IsInRole("Client") && Thread.CurrentPrincipal.Identity.userID != userID)
        { 
            //Kick them out of here.
        }
        return "value";
    }

这是可行的,但似乎所有权检查应该在到达控制器之前的单个位置,并且应该可在整个应用程序中重复使用。我猜最好的地方是自定义AuthorizationFilterAttribute或自定义AuthorizeAttribute,并可能创建一个新角色ClientOwner。

This will work, but it seems like the check for ownership should happen in a single location before it reaches the controller and should be reusable throughout an application. I am guessing the best place would either be a custom AuthorizationFilterAttribute or a custom AuthorizeAttribute and maybe create a new role ClientOwner.

    [Authorize(Roles = "Administrator, CallCenter, ClientOwner")]
    public string Get(int userID)
    {
        return "value";
    }

自定义AuthorizeAttribute

Custom AuthorizeAttribute

    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        //If user is already authenticated don't bother checking the header for credentials
        if (Thread.CurrentPrincipal.Identity.IsAuthenticated) { return; }

        var authHeader = actionContext.Request.Headers.Authorization;

        if (authHeader != null)
        {
            if (authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) &&
                !String.IsNullOrWhiteSpace(authHeader.Parameter))
            {
                var credArray = GetCredentials(authHeader);
                var userName = credArray[0];
                var password = credArray[1];

                //Add Authentication
                if (true)
                {
                    var currentPrincipal = new GenericPrincipal(new GenericIdentity(userName), null);
                    var user = GetUser(userName);

                    foreach (var claim in user.Cliams)
                    {
                        currentPrincipal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimTypes.Role, claim);
                    }
                    //**************Not sure best way to get UserID below from url.***********************
                    if (user.userTypeID = UserTypeID.Client && user.userID == UserID)
                    {
                        currentPrincipal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimTypes.Role, "ClientOwner"));
                    }
                    Thread.CurrentPrincipal = currentPrincipal;
                    return;
                }
            }
        }

        HandleUnauthorizedRequest(actionContext);
    }}

有人可以指出我的意思吗?有关处理个人授权的最佳地点的正确方向虚拟用户?应该还是在控制器中完成此操作,还是应该将其移至自定义AuthorizationFilterAttribute或自定义AuthorizationAttribute,还是应该在其他地方处理?如果适当的位置位于自定义属性中,那么获取用户ID的最佳方法是什么,我应该像上面的示例一样创建一个新角色,还是应该做一些不同的事情?

Can someone point me in the right direction as to the best place to handle the authorization of the individual user? Should this still be done in the controller or should I move it to a custom AuthorizationFilterAttribute or a custom AuthorizationAttribute or is there somewhere else this should be handled? If the proper place is in a custom attribute, then what is the best way to get the userID and should I create a new role like the example above or should I do something different?

这是一个常见的场景,我很努力地寻找上述场景的示例,对此我感到非常惊讶。这使我相信,要么每个人都在控制器中进行检查,要么还有另一个我不知道的术语,所以我在Google上的成绩不佳。

This is a common scenario and I am very surprised that I have struggled to find examples of the above scenario. This leads me to believe that either everyone is doing the check in the controller or there is another term I am not aware of so I am not getting good google results.

推荐答案

我认为您可能会混淆授权权限。 动态授权不是您要做的事情。

I think you may be getting authorization and permissions confused. "Dynamic authorization" isn't something you ever do.

授权是验证作者的行为。

Authorization is the act of verifying an author.


  1. 请求声称它是从爱丽丝发送的。

  2. 请求出示密码或授权令牌,以证明请求者是爱丽丝。

  3. 服务器验证密码或授权令牌是否匹配其对Alice的记录。

权限是指定谁可以执行的业务逻辑

Permissions are the business logic that specifies who can do what in your system.


  1. 请求已被授权,我们知道它来自爱丽丝。

  2. Alice请求删除重要资源。

  3. Alice是管理员吗?如果没有,请告诉她她不能这样做,因为她没有许可。 (403禁止访问)

内置的 [Authorize] 属性可让您(可选)指定允许访问资源的 Roles 。在我看来,将权限指定为授权的一部分的选项有些错误。

The built-in [Authorize] attribute lets you optionally specify Roles that are permitted to access a resource. That option to specify permissions as part of authorization is slightly misplaced, in my opinion.

我的建议是将授权留为纯粹用于验证请求作者的过程。 BasicAuthHttpModule 此处描述与您已经想要的东西接近。

My advice would be to leave authorization as purely the process of verifying the author of a request. The BasicAuthHttpModule described here is close to what you want already.

非平凡的权限逻辑需要在您的操作主体中处理。下面是一个示例:

Non-trivial permissions logic needs to be handled inside of your action body. Here's an example:

//Some authorization logic:
//  Only let a request enter this action if the author of
//  the request has been verified
[Authorize]
[HttpDelete]
[Route("resource/{id}")]
public IHttpActionResult Delete(Guid id)
{
    var resourceOwner = GetResourceOwner(id);

    //Some permissions logic:
    //  Only allow deletion of the resource if the
    //  user is both an admin and the owner.
    if (!User.IsInRole("admin") || User.Identity.Name != resourceOwner)
    {
        return StatusCode(HttpStatusCode.Forbidden);
    }

    DeleteResource(id);
    return StatusCode(HttpStatusCode.NoContent);
}

在此示例中,很难将权限逻辑作为属性传达在操作上,因为只有在您实际上从后端存储设备获得资源所有者信息之后,才能评估将当前用户与资源所有者进行比较的那部分权限。

In this example, it would be difficult to convey the permissions logic as an attribute on the action, because the portion of the permissions that compares the current user to the resource owner can only be evaluated after you have actually gotten the resource owner info from your backend storage device.

这篇关于ASP.NET WebAPI动态授权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆