【问题标题】:Role Based Authentication for web API not workingWeb API 的基于角色的身份验证不起作用
【发布时间】:2020-12-21 16:59:40
【问题描述】:

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

我有一个控制器类,其中控制器有一个名为 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());
    }
   }
 }

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

【问题讨论】:

  • 如果您没有将调用的值分配给任何东西,为什么还要使用user(alias); 创建用户?
  • 你有它的方式,你还不如使用[Authorize(Roles = "role1, role2, role3")]
  • @insane_developer 是的,我还有其他可以通过多个角色访问的控制器。
  • @JuanR ,对不起,我已经添加了 user(alias) 方法的代码。请您检查一次。我不了解这里的角色机制。你能帮忙吗?
  • @Naurtosan 你试过[Authorize(Constants.Roles.Admin)]吗?那应该做你需要的。我认为除了检查管理员角色之外,您还需要一些东西,这就是这样做的。

标签: c# authentication asp.net-mvc-4 asp.net-web-api rbac


【解决方案1】:

如果您查看 the source code 中的 AuthorizeAttribute 类,您会发现它使用控制器上下文请求的主体来执行授权,因此请改写 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);
}

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

【讨论】:

  • 谢谢,@JuanR。该修复程序正在运行。这么晚才回复很抱歉。你救了我。并且请始终与像我这样的菜鸟分享知识:)。
  • @Naurtosan 不用担心。我很高兴能够提供帮助。
【解决方案2】:

这对我有用

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

【讨论】:

  • 我正在寻找的是基于角色的身份验证
  • 这是基于角色的身份验证,此功能userManager.GetRoles 将为您提供用户所在的所有角色。
  • 如果您正在寻找基于声明的身份验证,这将不起作用!
  • 这不是 [Authorize(Constants.Roles.Admin)] 开箱即用的吗?只有管​​理员角色的用户有权访问资源。我已经反复这样做了。我在这里错过了什么?
  • 不确定,我总是这样。
【解决方案3】:

您无需为此创建自己的授权过滤器。 使用内置的[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 类来自命名空间System.Security.Claims

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

【讨论】:

  • 我正在处理 Web API 授权。因此,只有在 myauthorize 类中,我才能将角色分配给用户。但有些地方会失败。
  • 你能分享你如何“登录”用户的代码吗?您如何在该操作中分配声明?
  • 如您在上面的代码中看到的,我们有通过传递一些 Jwt 令牌来调用它们的 api。将角色分配给用户的 Myauthorize 类中的代码。但是 Api 在没有管理员权限的情况下一直在调用。
猜你喜欢
  • 2013-05-29
  • 2020-03-13
  • 1970-01-01
  • 1970-01-01
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
相关资源
最近更新 更多