问题描述
使用基于角色的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());
}
}
}
如何根据访问级别在此处限制用户?
解决方法
如果您查看AuthorizeAttribute
类的the source code,您会发现它使用控制器上下文请求的主体执行授权,因此请改写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);
}
我将避免评论设计本身。这应该可以解决您的问题。
,这就是对我有用的
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
,
您无需为此创建自己的授权过滤器。
使用内置的[Authorize(Roles = "Admin")]
-将检查用户是否有一个称为“ http://schemas.microsoft.com/ws/2008/06/identity/claims/role”的声明,并且该值是否与您输入的那个authorize属性中的一个,授权将成功。
因此,在您的情况下,请确保在登录用户时使用以下角色设置其主张:
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Role,"Admin"),//here set the users role
// ... other claims
};
(ClaimTypes
类来自命名空间System.Security.Claims
)
然后[Authorize(Roles = "Admin")]
应该可以正常工作