asp.net-mvc MVC 角色授权
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22724798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MVC Role Authorization
提问by drinu16
I am trying to implement a role authorization mechanism which checks the roles of the current logged in user, if the user is in the right role, he/she is allowed, else display error view.
我正在尝试实现一种角色授权机制,该机制检查当前登录用户的角色,如果用户处于正确的角色,则允许他/她,否则显示错误视图。
The problem is that when the user tries to access the below method in the controller, he does get into the RoleAuthorizationAttribute class and gets verfied but then the method in the controller is not executed.
问题是,当用户尝试访问控制器中的以下方法时,他确实进入了 RoleAuthorizationAttribute 类并得到了验证,但控制器中的方法并未执行。
Note : the user has the Client role
注意:用户具有客户端角色
Controller method
控制器方法
[RoleAuthorization(Roles = "Client, Adminsitrator")]
public ActionResult addToCart(int ProductID, string Quantity)
{
tempShoppingCart t = new tempShoppingCart();
t.ProductID = ProductID;
t.Username = User.Identity.Name;
t.Quantity = Convert.ToInt16(Quantity);
new OrdersService.OrdersClient().addToCart(t);
ViewData["numberOfItemsInShoppingCart"] = new OrdersService.OrdersClient().getNoOfItemsInShoppingCart(User.Identity.Name);
ViewData["totalPriceInSC"] = new OrdersService.OrdersClient().getTotalPriceOfItemsInSC(User.Identity.Name);
return PartialView("quickShoppingCart", "Orders");
}
Role Authentication class
角色认证类
[System.AttributeUsage(System.AttributeTargets.All,AllowMultiple = false, Inherited = true)]
public sealed class RoleAuthorizationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
List<String> requiredRoles = Roles.Split(Convert.ToChar(",")).ToList();
List<Role> allRoles = new UsersService.UsersClient().GetUserRoles(filterContext.HttpContext.User.Identity.Name).ToList();
bool Match = false;
foreach (String s in requiredRoles)
{
foreach (Role r in allRoles)
{
string rName = r.RoleName.Trim().ToString();
string sName = s.Trim();
if (rName == sName)
{
Match = true;
}
}
}
if (!Match)
{
filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
}
base.OnAuthorization(filterContext);
}
}
Could you please tell me what I am doing wrong
你能告诉我我做错了什么吗
回答by drinu16
Since I had the roles of the users in the database I had to check against the database so I included this method in the global.asax
由于我在数据库中拥有用户的角色,因此我必须对照数据库进行检查,因此我将此方法包含在 global.asax 中
protected void Application_AuthenticateRequest(object sender, EventArgs args)
{
if (Context.User != null)
{
IEnumerable<Role> roles = new UsersService.UsersClient().GetUserRoles(
Context.User.Identity.Name);
string[] rolesArray = new string[roles.Count()];
for (int i = 0; i < roles.Count(); i++)
{
rolesArray[i] = roles.ElementAt(i).RoleName;
}
GenericPrincipal gp = new GenericPrincipal(Context.User.Identity, rolesArray);
Context.User = gp;
}
}
Then I could use the normal
然后我可以使用正常的
[Authorize(Roles = "Client, Administrator")]
On top of the actionResult methods in the controllers
在控制器中的 actionResult 方法之上
This worked.
这奏效了。
回答by Henry Guillen
Your original code was close, but the problem lies here:
您的原始代码很接近,但问题出在这里:
base.OnAuthorization(filterContext);
Unconditionally calling the base class means you are requiring the decorated roles to be found in BOTH the UsersService and the built-in Role provider. If the role provider isn't configured to return the same set of roles (which they wouldn't if the default AuthorizeAttribute isn't sufficient for you) then this will obviously result in the Authorization test always returning false.
无条件调用基类意味着您需要在 UsersService 和内置角色提供程序中都可以找到装饰角色。如果角色提供程序未配置为返回相同的一组角色(如果默认 AuthorizeAttribute 对您来说不够,则不会返回相同的角色集),那么这显然会导致授权测试始终返回 false。
Instead you could add a separate property to the derived Attribute such as
相反,您可以向派生的 Attribute 添加一个单独的属性,例如
public string RemoteRoles { get; set; }
and replace
并替换
List<String> requiredRoles = Roles.Split(Convert.ToChar(",")).ToList();
with:
和:
List<String> requiredRoles = RemoteRoles.Split(Convert.ToChar(",")).ToList();
And decorate your controller like such:
并像这样装饰你的控制器:
[RoleAuthorization (RemoteRoles = "Client, Administrator")]
回答by fmoliveira
If you're using MVC 5 you have to enable lazy loading in your DbContext by putting the following line in your DbContext initialisation.
如果您使用的是 MVC 5,则必须通过在 DbContext 初始化中放置以下行来在 DbContext 中启用延迟加载。
this.Configuration.LazyLoadingEnabled = true;
In MVC 5 default project you'll add it to ApplicationDbContext.cs file.
在 MVC 5 默认项目中,您将把它添加到 ApplicationDbContext.cs 文件中。
I'm not sure if this is particular to MVC 5, to Identity 2.0, or affect other versions. I'm using this setup and enabling lazy loading make all the default role schema works. See https://stackoverflow.com/a/20433316/2401947for more info.
我不确定这是否特定于 MVC 5、Identity 2.0 或影响其他版本。我正在使用此设置并启用延迟加载使所有默认角色架构都能正常工作。有关更多信息,请参阅https://stackoverflow.com/a/20433316/2401947。
Additionally, if you're using ASP.NET Identity 2.0 default permission schema, you don't have to implement Application_AuthenticateRequest as Darren mentioned. But if you're using custom authorisation tables, then you have to implement it as well.
此外,如果您使用 ASP.NET Identity 2.0 默认权限架构,则不必像 Darren 提到的那样实现 Application_AuthenticateRequest。但是如果您使用自定义授权表,那么您也必须实现它。

