4

我一直在阅读大量文章和论坛,但我仍然无法弄清楚......我正在使用 Visual Studio Express 2012 for Web 构建一个互联网应用程序,其中包含 MVC4+Razor+Entity Framework CodeFirst。

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

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

为了要求身份验证,我在控制器方法的顶部添加了注释[Authorize](没有参数),它无需进行任何额外配置或添加任何其他内容即可工作。此外,当我查看自动创建的数据库时,我看到了一个名为 pages_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

谢谢!

4

2 回答 2

6

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

[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方法在Seed方法中初始化 Web 矩阵安全数据库。

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

于 2013-01-25T19:22:44.347 回答
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 中的 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 控制的“About”页面。哪个;)

于 2013-01-28T11:02:39.643 回答