使用simplemembership在新的MVC 4互联网模板中实现基于角色的身份验证

53
我喜欢MVC 4互联网模板中的新SimpleMembership功能,它具有指向OAuth的链接以进行外部登录,并且在VS 2012 RTM中工作。大多数身份验证功能都在工作。然而,即使花费了8个小时以上,我仍无法实现基于角色的授权来处理我的控制器。 SimpleMembership并不简单。
我已经搜索了stackoverflow,谷歌,并阅读了John Galloway的最新文章,尝试了许多建议,但仍然无法解决此问题。一切始于出现Sql连接错误,而当连接字符串和其他所有内容都正确时,无法弄清楚原因。花费了很多时间才发现是Roles类引起了问题。
控制器上的[Authorize]属性对于基本身份验证仍然像以前一样工作。但是,每次我尝试使用Roles时,它会给出sql连接错误(因为它会恢复到旧的DefaultRolesProvider,该提供程序尝试连接到默认的SqlExpress aspnetdb文件并失败)。所以,类似这样的东西:
[Authorize(Roles="admin")]

无法正常工作。如果我回到旧的asp.net成员资格提供程序,它将会工作,但那样我就会失去简单的数据库表、基于令牌的确认和恢复、更安全的密码哈希以及更重要的OAuth外部登录。

唯一在代码和razor视图中有效的是

User.IsInRole("admin")

这对于菜单项等内容来说是可以的,但在每个控制器操作中实现起来非常麻烦(而且我不喜欢它一次只测试一个角色)。 我将非常感激任何解决此问题的指导。
2个回答

69

我在Mehdi Golchin的这里找到了一个答案,似乎可以解决以下问题:

[Authorize(Roles="admin,editor,publisher")]
如果我也在主页控制器中添加这个:
 [InitializeSimpleMembership]

因为这个属性在Accounts控制器上,所以SimpleMembership数据库只会在第一次使用账户控制器(如登录/注册)时才会初始化。即使当前用户通过cookie登录,也不会初始化数据库,因此会抛出错误。一个解决方法是将此属性放在主页控制器上,在启动网站时调用。但是,然后需要将其放置在每个控制器上,因为我根据角色检查角色并显示不同的菜单项。

这是糟糕的设计,因为数据库应该在App_Start上初始化,而不是在第一次使用时初始化。

我试过放置

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

Global.asaxApplication_Start()方法中,使用User.IsInRole("admin")检查菜单项的角色,并对任何带有[Authorize(Roles="admin")]属性的控制器抛出错误,即使应用了额外的[InitializeSimpleMembership]属性。

因此,现在的解决方案是将`[InitializeSimpleMembership]`放在所有控制器上,因为用户可能最初通过外部链接访问任何页面。

它仍然无法弄清楚如何初始化SimpleRolesProvider类,以执行更多的角色管理,而不仅仅是User.IsInRole()

这些东西在webmatrix webpages网站中工作得更好,显然端口到MVC并不完整。 它与默认的asp.net成员资格提供程序冲突并且混淆。

编辑 好吧,我没有想到可以通过将这行放入App_Start文件夹中的FilterConfig.cs来全局应用[InitializeSimpleMembership]过滤器:

filters.Add(new InitializeSimpleMembershipAttribute());

现在问题解决了,接下来需要解决SimpleRolesProvider初始化的问题,否则我就得自己编写角色提供程序。

更新:

这篇文章(Scott Allen的文章)解决了我所有的问题。

将以下内容包含在web.config中:

<roleManager enabled="true" defaultProvider="simple">
  <providers>
    <clear/>
    <add name="simple" type="WebMatrix.WebData.SimpleRoleProvider,               WebMatrix.WebData"/>
  </providers>      
</roleManager>
<membership defaultProvider="simple">
  <providers>
    <clear/>
    <add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider,                          WebMatrix.WebData"/>
  </providers>
</membership>

通过以下方式,Roles和Membership类的所有方法都变得可用,并可以在代码中进行初始化:

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

7
以上配置内容需放置在<system.web>标签内。 - BladeLeaf
谢谢你,Ahmed,你救了我一次头疼的经历! - s0nica
谢谢您先生。您不知道这对我有多大帮助。 - programad
1
对于基于角色的身份验证,例如使用[Authorize(Roles="Admin")]时,如果用户已登录但WebSecurity未初始化,则会出现错误,因为授权过滤器首先运行。将InitializeSimpleMembershipAttribute设置为IAuthorizationFilter请参见文章 - edteke

6

当我将我的Web应用从VS2010/MVC3移植到VS2012/MVC4时,遇到了同样的问题。

但是我无法让[InitializeSimpleMembership]起作用。

后来发现将以下内容添加到您的web.config中即可解决问题:

  <appSettings>
    <add key="enableSimpleMembership" value="false" />
  </appSettings>

现在一切都像以前一样正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接