自定义授权属性角色不起作用 Web api 身份验证

Custom Authorize attribute role is not working web api authentication

我在使用 Web api Azure 广告身份验证时遇到问题

我有如下所示的控制器,该控制器给出了正确的响应,但具有自定义授权角色的控制器抛出错误,因为“已针对此请求进行了身份验证”。

[RoutePrefix("api/hospitals")]
public class hospitals : ApiController
{
    [Route("GetAll")]
    [HttpGet]
    [Authorize]
    public async Task<IEnumerable<Hospitals>> GetAll()
    {
        // return ok;
    }
    [Route("Getbeds")]
    [HttpGet]
    [SmAuthorize(Constants.Roles.Admin,
        Constants.Roles.HotSpitalAdmin,
        Constants.Roles.QA)]
    public async Task<IEnumerable<Hospitals>> Getbeds()
    {
        // return ok;
    }
}

Getbeds 方法抛出错误“已请求授权”。

也请找我自定义属性class

public class SmAuthorizeAttribute : AuthorizeAttribute
{
    public SmAuthorizeAttribute(params string[] roles)
    {
        this.Roles = string.Join(",", roles.Select(s => s.Trim()).ToArray());
    }
}

任何人都可以帮忙吗?

你可以参考 Derek Greer对Dot Net core的SO问题的回答,另外我会在下面重申答案-

ASP.Net 核心团队推荐的方法是使用完整记录的新策略设计 here。新方法背后的基本思想是使用新的 [Authorize] 属性来指定一个“策略”(例如 [Authorize( Policy = "YouNeedToBe18ToDoThis")],其中该策略在应用程序的 Startup.cs 中注册以执行一些代码块(即确保用户有 18 岁或以上的年龄声明)。

策略设计是对框架的重要补充,ASP.Net 安全核心团队的引入值得称赞。也就是说,它并不适合所有情况。这种方法的缺点是它无法为最常见的简单断言给定控制器或操作需要给定声明类型的需求提供方便的解决方案。如果一个应用程序可能有数百个离散的权限来管理对单个 REST 资源的 CRUD 操作(“CanCreateOrder”、“CanReadOrder”、“CanUpdateOrder”、“CanDeleteOrder”等),新方法要么需要重复的一对一策略名称和声明名称之间的一个映射(例如 options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));),或者编写一些代码来执行这些注册在 运行 时间(例如从数据库中读取所有索赔类型并在循环中执行上述调用)。对于大多数情况,这种方法的问题是它是不必要的开销。

虽然 ASP.Net 核心安全团队建议永远不要创建自己的解决方案,但在某些情况下,这可能是最谨慎的开始选择。

以下是一个实现,它使用 IAuthorizationFilter 提供一种简单的方法来表达对给定控制器或操作的声明要求:

public class ClaimRequirementAttribute : TypeFilterAttribute
{
    public ClaimRequirementAttribute(string claimType, string claimValue) : base(typeof(ClaimRequirementFilter))
    {
        Arguments = new object[] {new Claim(claimType, claimValue) };
    }
}

public class ClaimRequirementFilter : IAuthorizationFilter
{
    readonly Claim _claim;

    public ClaimRequirementFilter(Claim claim)
    {
        _claim = claim;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var hasClaim = context.HttpContext.User.Claims.Any(c => c.Type == _claim.Type && c.Value == _claim.Value);
        if (!hasClaim)
        {
            context.Result = new ForbidResult();
        }
    }
}


[Route("api/resource")]
public class MyController : Controller
{
    [ClaimRequirement(MyClaimTypes.Permission, "CanReadResource")]
    [HttpGet]
    public IActionResult GetResource()
    {
        return Ok();
    }
}

.NET Framework-

this 部分答案

推荐的自定义属性 class:

public class CustomAuthorize : System.Web.Http.AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    protected override Boolean IsAuthorized(HttpActionContext actionContext)
    {
        var currentIdentity = actionContext.RequestContext.Principal.Identity;
        if (!currentIdentity.IsAuthenticated)
            return false;

        var userName = currentIdentity.Name;
        using (var context = new DataContext())
        {
            var userStore = new UserStore<AppUser>(context);
            var userManager = new UserManager<AppUser>(userStore);
            var user = userManager.FindByName(userName);

            if (user == null)
                return false;

            foreach (var role in permissionActions)
                if (!userManager.IsInRole(user.Id, Convert.ToString(role)))
                    return false;

            return true;
        }
    }
}