使用具有上下文相关角色的授权声明

本文关键字:角色 授权 声明 上下文 | 更新日期: 2023-09-27 18:24:43

首先,我是C#授权领域的新手。我已经阅读了很多关于IPrincipalIIdentityClaim的内容,但我无法将其映射到我当前的应用程序。

考虑一下:我有三个用户:Alice、Bob和Charlie,他们都有Files。假设我是作为Alice登录的,Bob和Charlie与Alice共享了对他们文件的权限。现在,Bob给了Alice r/w访问权限,但Charlie只给了Read访问权限。

API的公开方式是通过WebApi作为REST端点(属性路由)。理想情况下,我会在端点上放置另一个属性,并声明它需要例如:

GET    /{user}/files/{fileId} // Gets: Claim("files", "read")
DELETE /{user}/files/{fileId} // Gets: Claim("files", "delete")

这里的问题是,我不知道如何评估这些索赔,因为它们依赖于user的值。在示例中,user是Bob或Charlie,而我以Alice身份登录。

有人能帮我建立这样一个系统吗?我很乐意使用一些特定领域的术语或一篇好的博客文章。

使用具有上下文相关角色的授权声明

有一个很好的关于声明授权的教程:http://bitoftech.net/2015/03/31/asp-net-web-api-claims-authorization-with-asp-net-identity-2-1/

但您也可以使用基于角色的方法,并检查用户是否可以使用您的业务逻辑访问文件。

您不需要在API的路由中指定用户。保持你的路线通用:

GET    /files/{fileId}
DELETE /files/{fileId} 

首先,你可以创建一个BaseApiController,它将保存你的控制器的用户信息:

public class BaseApiController : ApiController
{
    public Guid UserID { get; set; }
}

您可以使用自定义授权属性装饰GET和DELETE方法:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
public class CustomAuthorize : AuthorizeAttribute
{
    protected override bool IsAuthorized(HttpActionContext actionContext)
    {
        IPrincipal principal = ((BaseApiController)actionContext.ControllerContext.Controller).User;
        //is the user already logged in on the system. This would work perfectly if you have a cookie in your web application authorizing the user
        bool isAuthenticated = principal != null && principal.Identity.IsAuthenticated;
        if (!isAuthenticated)
        {
            // Deny request or you could also check the request headers for an authorization token
            return false;
        }
        // Save UserID to be used later in your controllers
        ((BaseApiController)actionContext.ControllerContext.Controller).UserID = UserID;
        // Authorize user, or you could also check if the user has the correct roles 
        return true;
    }
}

在您的控制器中:

public FilesController : BaseApiController 
{
    [CustomAuthorize]
    public HttpResponseMessage Get(int fileID) 
    {
        return filesAccess.getFile(fileID, UserID);
    }
}