我究竟如何在Asp.NET MVC 4中使用Roles?

时间:2013-01-25 17:27:25

标签: asp.net-mvc-4 visual-studio-2012 roles membership

我一直在阅读大量的文章和论坛,但我仍然无法弄明白...... 我正在使用Visual Studio Express 2012 for Web构建一个Internet应用程序,使用MVC4 + Razor + Entity Framework CodeFirst。

据我了解,使用SimpleMembership管理MVC4中的用户和角色比以前的版本更简单,应该相当简单。

在我的应用程序中,我只需要授权某些用户组(例如,只有管理员才能访问某些页面)。我理解这是通过将参数传递给[Authorize]注释来实现的:[Authorize(Roles =“Admins”)] 但是,我如何创建这些角色以及如何向其添加用户?

为了要求身份验证,我在控制器方法的基础上添加了注释 [授权] (没有参数),并且无需进行任何额外配置或添加任何其他内容即可运行。此外,当我查看自动创建的数据库时,我看到一个名为webpages_UsersInRoles的表,其中包含UserId和RoleId列。所有这一切使我认为这必须是一个非常简单的任务,因为所有似乎已经准备就绪并且可以使用,但我无法弄清楚如何;)

到目前为止我尝试过的(它没有用)是这样的: 我有一个继承自DropCreateDatabaseIfModelChanges的“DataContextDbInitializer”类。 Seed方法在该类中被覆盖,我添加了这个(我必须导入System.Web.Security):

Membership.CreateUser("user1", "123456");
Roles.CreateRole("Admins");
Roles.AddUserToRole("user1", "Admins");

我还在Web.config文件的标记中插入了这个标记:

<roleManager
enabled="true"
cacheRolesInCookie="true" >
</roleManager>

为了尝试一下,我在控制器的操作方法之上添加了[Authorize(Roles =“Admins”)],然后以“admin”身份登录并尝试访问该方法,但没有运气:(< / p>

我不知道还有什么我想念的...... 如果有人能指导我完成这件事,我会非常高兴,因为它让我疯狂:P

谢谢!

2 个答案:

答案 0 :(得分:6)

我的猜测是你的种子方法没有被调用。通过在方法中放置一个断点并在调试器中运行它来验证是否正在调用它。除非您对应用程序进行了其他更改,否则不会使用EF迁移。默认情况下,使用 InitializeSimpleMembershipAttribute 初始化数据库。您将看到此属性已添加到帐户控制器,如以下代码所示。

[Authorize]
[InitializeSimpleMembership]
public class AccountController : Controller
{
  ....
}

这样,只有在访问 AccountController 时才会调用它。您将在Filters \ InitializeSimpleMembershipAttribute.cs中找到该定义。这是来自这个类的代码片段,可能是为什么它不被调用的线索。

// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();

InitializeSimpleMembershipAttribute 中的许多代码用于处理不将表单身份验证用于MVC应用程序的场景。如果您将始终使用表单身份验证,则可以删除此代码并自行初始化数据库。只需从AccountController中删除此属性,并将您自己的初始化代码放在Global.asax Application_Start 方法中。您可以在 Application_Start 方法

中添加类似的内容
Database.SetInitializer<UsersContext>(new MyDBInitializer());

种子方法看起来像这样

WebSecurity.InitializeDatabaseConnection("DefaultConnection",
      "UserProfile", "UserId", "UserName", autoCreateTables: true);

var roles = (SimpleRoleProvider)Roles.Provider;
var membership = (SimpleMembershipProvider)Membership.Provider;

if (!roles.RoleExists("Admin"))
{
     roles.CreateRole("Admin");
}
if (membership.GetUser("user1", false) == null)
{
     membership.CreateUserAndAccount("user1", "123456");
}
if (!roles.GetRolesForUser("user1").Contains("Admin"))
{
    roles.AddUsersToRoles(new[] { "user1" }, new[] { "Admin" });
} 

请注意,您需要通过调用 WebSecurity.InitializeDatabaseConnection 方法在种子方法中初始化Web矩阵安全数据库。

您可以在此blog post中找到有关播种SimpleMembership的更多详细信息,其中包含示例项目的完整源代码。

答案 1 :(得分:3)

最后,我设法让整个事情发挥作用!

我的种子方法现在看起来像这样:

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

if (!Roles.RoleExists("Admins"))
{
    Roles.CreateRole("Admins");
}
if (!WebSecurity.UserExists("admin"))
{
    WebSecurity.CreateUserAndAccount("admin", "123456");
}
if (!Roles.GetRolesForUser("admin").Contains("Admins"))
{
    Roles.AddUsersToRoles(new[] { "admin" }, new[] { "Admins" });
}
base.Seed(context);

Global.asax中的My App_Start如下所示:

Database.SetInitializer(new DataContextDbInitializer());
DataContext c = new DataContext();
c.Database.Initialize(true);

我不确定这是否真的在做什么,但我在Web.config中的system.web标记内有这个:

<roleManager enabled="true" cacheRolesInCookie="true" />

我还从AccountController中删除了[InitializeSimpleMembership],在AccountModels中删除了UsersContext类。我把这一点移到我自己的上下文类中:

public DbSet<UserProfile> UserProfiles { get; set; }

然后,为了测试一切是否正常,我在HomeController的About()方法的顶部使用[Authorize(Roles =“Admins”)]注释。如果事情按预期工作,这应该强制我以admin / 123456登录,以便能够看到由HomeController / About控制的“关于”页面。哪个;)