ASP.NET动态角色基于操作访问

时间:2012-11-26 22:29:51

标签: asp.net asp.net-mvc roleprovider

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

我知道我可以写下这样的内容:

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

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

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

我看了网但没找到任何东西......

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

2 个答案:

答案 0 :(得分:3)

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

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

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 / }

您还可以检查asp.net mvc的Authorize属性上的角色:

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

编辑

您可以拥有一个表,将权限“Admin”与某些权限相关联(编辑注释,删除注释等......可以存储在数据库的表中)。尝试这样的方法来实现自定义检查权限:

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
}

答案 1 :(得分:0)

Felipe Oriani建议的解决方案不起作用

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

  

User.IsInRole( “管理员”)

它总是返回false。所以我想出了另一个在自定义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);
}

}

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

[AuthenticateRequest]
public class AuthorizedController: Controller
{

}

然后你绝对可以使用

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

希望这有帮助