ClaimsPrincipalPermission与ClaimsAuthorization属性使用不同的信息,最好使用

时间:2015-05-22 14:07:14

标签: c# asp.net-web-api claims-based-identity

我正在尝试在各个webapi上实现声明基础授权......但是我不希望用户声称与webapi紧密耦合。使用ClaimsPrincipalPermissions我可以获得所需的解耦,因为我可以将用户分配给数据库中的资源。例如

Webapi方法

    [ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Manage", Resource = "Roles")]
    public async Task<IHttpActionResult> GetRole(string Id)
    {
        var role = await AppRoleManager.FindByIdAsync(Id);

        if (role != null)
        {
            return Ok(ModelFactory.Create(role));
        }

        return NotFound();

    }

使用自定义授权管理器

public class AuthorizationManager : ClaimsAuthorizationManager
{
    public override bool CheckAccess(AuthorizationContext context)
    {
        //return base.CheckAccess(context);
        string resource = context.Resource.First().Value;
        string action = context.Action.First().Value;

        if (action == "Manage" && resource == "Roles")
        {
            // check for roles
            //context.Principal.IsInRole("Admin");
            bool hasRolesManagement = context.Principal.HasClaim("ManageRoles", "True");
            return hasRolesManagement;
        }

        return false;
    }

}

我可以对特定的登录用户进行适当的检查,检查他们对他们正在攻击的资源的声明。但是,我无法以这种方式将适当的未经授权的响应反馈给用户。我发现的另一个例子是webapi如下所示

    [ClaimsAuthorization(ClaimType="ManageRoles", ClaimValue="True")]
    [Route("")]
    public IHttpActionResult Get()
    {
        return Ok();
    }

然后使用自定义声明授权属性

public class ClaimsAuthorizationAttribute : AuthorizationFilterAttribute
{
    public string ClaimType { get; set; }
    public string ClaimValue { get; set; }

    public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
    {

        var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;

        if (!principal.Identity.IsAuthenticated)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            return Task.FromResult<object>(null);
        }

        if (!(principal.HasClaim(x => x.Type == ClaimType && x.Value == ClaimValue)))
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            return Task.FromResult<object>(null);
        }

        //User is Authorized, complete execution
        return Task.FromResult<object>(null);

    }
}

这使我可以访问actionContext以发回适当的statusCoded响应。

第二种方法的大注意事项是为api方法引入可访问性,以便我必须重新编译代码。

所以我的问题是如何获得第一种方法的灵活性,其中每个api被指定为资源,并且声明在数据库中被分配给资源,但仍然获得第二种方法的灵活性,我可以访问到动作上下文并能够返回正确的状态编码响应?我们不希望重新编译代码以允许其他角色/声明访问webapi资源。

我是新手,所以我对所有概念都没有透彻的理解,所以请告诉我是否遗漏了什么。

1 个答案:

答案 0 :(得分:0)

根据ClaimsPrincipalPermission.Demand

的文件
  

“如果当前委托人未获得指定行动的授权   在指定的资源上,抛出SecurityException;除此以外,   执行进行。“

然后解决方案是在解决方案中创建一个异常处理程序并返回UnAuthorized Http响应。 (我真的认为默认情况下ASP.Net会这样做,但我从来没有检查/反映过那个:)