Web API 的基于角色的身份验证无法正常工作

Role Based Authentication for web API not working

我在使用基于角色的 Web 身份验证时遇到问题 APi。

我有一个控制器 class,其中控制器有一个名为 Myauthorize 的自定义授权属性。 我在控制器中有一个方法,只能通过管理员访问才能访问。 但同样的方法也一直在调用 QA 访问权限。 有人可以帮忙解决以下问题吗?

请在下面找到代码。 控制器:

namespace Hosiptal.Controllers.office
{
 [MyAuthorize(Constants.Roles.Admin)]
 public class UserRolesController : ApiController
 {
    private readonly IRepository<EntityModels.Role> rolesRepository;

    public UserRolesController(IRepository<EntityModels.Role> rolesRepository)
    {            
        this.rolesRepository = rolesRepository;
    }

    // GET: Users
    [HttpGet]
    [Route("")]        
    public IEnumerable<Role> GetAll()
    {
        return this.rolesRepository.GetAll()
            .ToArray()
            .Select(r => Mapper.Current.Get<Role>(r));                
    }
  }
}

MyAuthorize 已关注。

namespace Hospital.Web.Filters.WebApi
{

 public class MyAuthorize: AuthorizeAttribute
 {
    private readonly string[] allowedroles;
    private static IUserProfileRepository UserProfileRepository
    {
        get { return IoC.Current.Resolve<IUserProfileRepository>(); }
    }
    public MyAuthorize(params string[] roles)
    {
        this.allowedroles = roles;
    }

    public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken 
      cancellationToken)
    {
        var claimsIdentity = actionContext.RequestContext.Principal.Identity as ClaimsIdentity;
        
        var alias = claimsIdentity.Name.Split('@')[0];
        if (alias == null)
        {
            throw new ArgumentNullException(nameof(actionContext));
        }
        user(alias);
        return base.OnAuthorizationAsync(actionContext, cancellationToken);
    }

    public static GenericPrincipal user(string userName)
    {
        userName = userName.ToUpper();

        var userProfile = UserProfileRepository.Get(userName) ?? new UserProfile()
        {
            UserName = userName,
            Roles = new List<Role>(),
            FirstLoginDateUtc = DateTime.UtcNow
        };
        return CreatePrincipal(userProfile);
    }
    public static GenericPrincipal CreatePrincipal(UserProfile user)
    {
        var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, 
                           user.UserName) }, "Custom");
        return new GenericPrincipal(identity, user.Roles.Select(i => 
              i.Name).ToArray());
    }
   }
 }

如何根据访问级别限制此处的用户?

这对我有用

public class AdminAuthorizeAttributee : AuthorizeAttribute
{

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if (AuthorizeRequest(actionContext))
        {
            return;
        }
        HandleUnauthorizedRequest(actionContext);
    }

    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);
    }

    private bool AuthorizeRequest(HttpActionContext actionContext)
    {
        try
        {
            var username = HttpContext.Current.User.Identity.Name;
            var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
            var user = userManager.Users.Where(a => a.UserName == username).FirstOrDefault();
            var rolesForUser = userManager.GetRoles(user.Id);
            var role = "Admin";



            if (rolesForUser.Contains(role))
            {
                return true;
            }
            return false;
        }
        catch (Exception ex)
        {
            return false;
        }

    }

}

并在控制器中

[AdminAuthorizeAttributee]
public class YOUR_Controller : ApiController

您不需要为此创建自己的授权过滤器。 使用 built-in [Authorize(Roles = "Admin")] - 这将检查用户是否有一个名为“http://schemas.microsoft.com/ws/2008/06/identity/claims/role”的声明,以及该值是否与您输入的值匹配在该授权属性中,授权将成功。

所以在你的情况下,只要确保当你登录用户时,他的声明设置为这样的角色:

            var claims = new List<Claim>()
            {
                new Claim(ClaimTypes.Role, "Admin"), //here set the users role
                     // ... other claims
            };

(ClaimTypes class 来自命名空间 System.Security.Claims)

然后 [Authorize(Roles = "Admin")] 应该可以正常工作

如果您查看 the source codeAuthorizeAttribute class,您将看到它使用控制器上下文请求的主体来执行授权,因此重写 IsAuthorized 方法相反,将您的代码移到那里并将您创建的主体分配给上下文请求的主体:

protected override bool IsAuthorized(HttpActionContext actionContext)
{
    var claimsIdentity = actionContext.RequestContext.Principal.Identity as ClaimsIdentity;

    var alias = claimsIdentity.Name.Split('@')[0];
    if (alias == null)
    {
        throw new ArgumentNullException(nameof(actionContext));
    }
    
    //This sets the context's principal so the base class code can validate
    actionContext.ControllerContext.RequestContext.Principal = user(alias);
    
    //Call the base class and let it work its magic
    return base.IsAuthorized(actionContext);
}

我不会对设计本身发表评论。这应该可以解决您的问题。