1

我希望在我的站点中实施基于角色的操作限制。例如,我希望限制仅由帖子作者或一组组编辑帖子的能力。

我知道我可以写类似的东西:

     if (User.IsInRole("Admin"))
          return true;
     return post.Author.AccountId == currentAccountId;

但我想知道我是否可以在不使用固定名称的角色的情况下动态地做到这一点。我希望创建一个控制面板,使管理员能够添加新角色。在每个角色创建/修改表单中,都有一个复选框,上面写着“可以编辑其他帖子吗?”。基于该值,我将在上述方法中采取行动。我在 PHP 中已经做过很多次了,但是因为它是我的第一个 ASP.NET MVC 站点,所以我想知道是否可以使用默认的 SQL 数据库结构(使用 MVC4 和新的 SimpleMembershipProvider,但我不介意写一个如果必须,自定义提供程序)。

我已经阅读了新的声明功能,但我没有看到在这种情况下可以使用它的方法,对吗?

我在网上看过,但没有找到任何东西......

非常欢迎任何建议!谢谢!

4

2 回答 2

3

是的,您可以使用表单身份验证进行一些自定义自动化,但您需要进行一些自定义。

首先,您必须自定义AuthenticateRequest应用程序的事件以使用角色,因此,Global.asax您必须设置代码以将其自定义为当前用户:

protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
    if (HttpContext.Current.User != null)
        if (HttpContext.Current.User.Identity.IsAuthenticated)
            if (HttpContext.Current.User.Identity is FormsIdentity)
            {
                var id = (FormsIdentity)HttpContext.Current.User.Identity;
                var ticket = id.Ticket;

                // Get the stored user-data, in this case, our roles
                string userData = ticket.UserData;
                string[] roles = userData.Split(',');
                HttpContext.Current.User = new GenericPrincipal(id, roles);
            }
}

当您对用户进行身份验证时,您必须设置角色,因此在您的控制器上,您必须使用如下代码对身份验证进行发布操作:

if (LoginService.Validate(userame, password) 
{
   FormsAuthentication.Initialize();

   var ticket = new FormsAuthenticationTicket(1,
                                 username, //user
                                 DateTime.Now, //begin
                                 DateTime.Now.AddHours(3), //timeout
                                 false, //remember?
                                 permission, // permission.. "admin" or for more than one  "admin,marketing,sales"
                                 FormsAuthentication.FormsCookiePath);

  var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,   FormsAuthentication.Encrypt(ticket));

  if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;

  HttpContext.Current.Response.Cookies.Add(cookie);
}

之后,您将能够使用类似于您的帖子的代码:

if (User.IsInRole("Admin"))
{ /** do something / }

或者

if (User.IsInRole("Admin") || (User.IsInRole("Marketing") && User.IsInRole("Sales")))
{ /** do something / }

也可以查看Authorizeasp.net mvc属性上的角色:

[Authorize(Roles = "Admin")]
public class CompanyController : Controller
{
   // actions
}

编辑

您可以有一个表来将权限“管理员”与某些特权(编辑评论、删除评论等......可以存储在数据库的表中)相关联。尝试这样的事情来实现自定义检查权限:

public static class UserExtension
{
    private static bool RoleHasPrivilege(string role, int privilege)
    {
        // performe a database/cache access to check if the role has the privilege
    }
    public static bool IsInRole(this IPrincipal user, string role, int privilege)
    {
        // check if the user authenticate has the "role" permission and the privilege is associate with this role...
        return user.IsInRole(role) && RoleHasPrivilege(role, privilege);
    }
}

你可以使用:

if (User.IsInRole("Admin", 1)) 
{
  // "Admins" has access
  // 1 - can edit posts... for sample
}
于 2012-11-26T23:11:05.147 回答
0

费利佩·奥里亚尼(Felipe Oriani)建议的某种解决方案不起作用

当在 global.asax 中实现并使用方法时

User.IsInRole("管理员")

它总是返回假。所以我想出了另一种在自定义 AuthorizeAttribute 中实现的解决方案。

public class AuthenticateRequestAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        HttpContextBase context = httpContext;

    if (context.User != null)
        if (context.User.Identity.IsAuthenticated)
            if (context.User.Identity is FormsIdentity)
            {
                FormsIdentity id = (FormsIdentity)context.User.Identity;
                FormsAuthenticationTicket ticket = id.Ticket;

                string userData = ticket.UserData;
                string[] roles = userData.Split(',');
                context.User = new GenericPrincipal(id, roles);
            }
    return base.AuthorizeCore(httpContext);
}

}

您可以使用此自定义属性代替内置的 [Authorize] 属性

[AuthenticateRequest]
public class AuthorizedController: Controller
{

}

那么你绝对可以使用

if (User.IsInRole("Admin"))
{ /** do something / }

希望这可以帮助

于 2013-04-29T10:04:32.737 回答