C# ClaimsPrincipalPermission与ClaimsAuthorization属性使用不同的信息,最好使用哪种信息

C# ClaimsPrincipalPermission与ClaimsAuthorization属性使用不同的信息,最好使用哪种信息,c#,asp.net-web-api,claims-based-identity,C#,Asp.net Web Api,Claims Based Identity,我正在尝试在单个webapi上实现基于声明的授权。。。但是,我不希望用户声称与webapi紧密耦合。使用ClaimsPrincipalPermissions,我可以获得所需的解耦,因为我可以将用户分配给数据库中的资源。比如说 Webapi方法 [ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Manage", Resource = "Roles")] public async Task<IHttpA

我正在尝试在单个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();

    }
我可以对某个特定的登录用户进行适当的检查,根据他们所访问的资源检查他们的声明。但是,我不能以这种方式将适当的未经授权的响应回退给用户。下面是我发现的另一个示例,其中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);

    }
}
公共类ClaimsAuthorizationAttribute:AuthorizationFilterAttribute
{
公共字符串ClaimType{get;set;}
公共字符串ClaimValue{get;set;}
AuthorizationAsync上的公共重写任务(HttpActionContext actionContext,System.Threading.CancellationToken CancellationToken)
{
var principal=actionContext.RequestContext.principal作为ClaimsPrincipal;
如果(!principal.Identity.IsAuthenticated)
{
actionContext.Response=actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
返回Task.FromResult(空);
}
if(!(principal.HasClaim(x=>x.Type==ClaimType&&x.Value==ClaimValue)))
{
actionContext.Response=actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
返回Task.FromResult(空);
}
//用户被授权,完成执行
返回Task.FromResult(空);
}
}
这使我能够访问actionContext,以发回正确的状态编码响应

第二种方法的一个重要警告是为api方法引入了可访问性,因为我必须重新编译代码

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


我是索赔新手,所以我还没有完全理解所有的概念,所以如果我遗漏了什么,请告诉我。

根据

“如果当前主体未被授权执行指定操作 在指定的资源上,将引发SecurityException;否则, 执行继续。”

然后,解决方案是在解决方案中创建一个异常处理程序,并返回一个未经授权的Http响应。(我真的认为ASP.Net在默认情况下做到了这一点,但我从未对此进行检查/反思:)

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);

    }
}