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

时间:2015-11-26 08:49:12

标签: c# rest asp.net-web-api authorization claims

首先,我是C#授权领域的新手。我一直在IPrincipalIIdentity Claim上阅读了很多内容,但是我无法将其映射到我当前的应用程序中。

考虑一下:我有三个用户:Alice,Bob和Charlie,他们都有文件。 假设我登录为Alice,Bob和Charlie与Alice共享对其文件的权限。现在,Bob给了爱丽丝的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身份登录时。

任何人都可以帮我解决如何设置这样的系统吗?我会对某些特定领域的术语或好的博客文章感到满意。

1 个答案:

答案 0 :(得分:0)

有一个关于声明授权的很好的教程: this article

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

您无需在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);
    }
}