SQL Server Compact 4作为ASP.NET MVC3中的成员资格提供程序

时间:2011-08-29 16:23:22

标签: sql-server asp.net-mvc-3 asp.net-membership

我创建了一个ASP.NET MVC3(Razor)Web应用程序,并将成员资格提供程序替换为MS的通用成员资格提供程序,通过NuGet安装,MDF数据库替换为SQL Server Compact 4 SDF数据库。

这个SDF一切正常,我可以从WSAT管理用户和角色,在登录我的开发工作站时进行验证等等。无论如何,我遇到了一些奇怪的行为,也许这只是其他用户遇到的事情:as as我将应用程序部署到生产服务器后,如果我尝试使用任何用户帐户登录(大约有60个帐户),我会因密码错误而被拒绝。我还将SDF数据库下载回我的开发机器,它适用于任何帐户。

我可以补充一点,我使用以下代码以编程方式创建了所有帐户:

MembershipUser user = Membership.GetUser(sName);
if (user != null)
{
    Membership.CreateUser(sName, sPassword, sEmail);
    AddUserToRole(sName, bIsAdmin? "administrator" : "member");
}

无论如何,他们看起来都很好并且活跃在WSAT中。

我尝试了管理员和会员帐户,但我得到了相同的结果。然而,数据库与我在本地成功使用的数据库相同。我还在页面上列出了所有具有锁定状态的用户帐户,以防万一,但它们都显示正常,并且在网上和本地都没有丢失。任何提示?

我的配置如下:

...
    <connectionStrings>
        <clear />
        <add name="ApplicationServices" 
                 connectionString="Data Source=|DataDirectory|\Organizer.sdf;" 
                 providerName="System.Data.SqlServerCe.4.0" />
        <add name="DefaultConnection" 
                 connectionString="Data Source=|DataDirectory|\Organizer.sdf;" 
                 providerName="System.Data.SqlServerCe.4.0" />
    </connectionStrings>
...
<membership defaultProvider="DefaultMembershipProvider">
    <providers>
        <clear />
        <add name="DefaultMembershipProvider" type="System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
    </providers>
</membership>
<profile defaultProvider="DefaultProfileProvider">
    <providers>
        <clear />
        <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
    </providers>
</profile>
<roleManager enabled="true" defaultProvider="DefaultRoleProvider">
    <providers>
        <clear />
        <add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" />
        <add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" />
        <add name="DefaultRoleProvider" type="System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" />
    </providers>
</roleManager>
...

更新:在一些随机尝试期间,我尝试将其中一个帐户设置为清除密码格式,而不是默认的哈希密码格式,这样可以正常工作,而所有其他未更改的帐户都会继续显示同样的问题。所以我必须推断出有一些关于散列密码的东西,它不适用于SqlServer Compact和/或我的Web配置。有人知道CF4在这方面的问题吗?

1 个答案:

答案 0 :(得分:2)

很抱歉打扰,我自己找到了解决方案,至少我希望这对其他新手有用:问题在于密码哈希的机器密钥。我认为它在我的开发人员机器和生产服务器中是相同的,但事实并非如此。我将密钥直接放在我的web.config中,以便此设置覆盖机器级别(如果有)。因此,将机器键设置为:

<machineKey validationKey="87172C641DE5712040FA42BFEBF230DD8D62D38CBAD58D67FA427414B767C3A64393747FCD46D5CE7E03E9798DD0491EDE6EB52FF1AC3D28FD4AEA2F693CCD32" decryptionKey="58F39AA799F12FF83F230607EAE74AD228E53D5519C51121129C21A841E385FD" validation="SHA1" decryption="AES" /> 

在web.config的system.web中。您可以从此处生成带有XML代码的键值:

http://aspnetresources.com/tools/machineKey

在我的情况下,我的所有用户帐户都已存在,因此我无法简单地从原始导入列表中重新创建它们。我宁愿使用一些代码重置所有密码。为此,请记住,Membership.ChangePassword通常会因为返回false而失败,至少对我而言,并非用户被锁定的情况(我检查了这个,因为这被认为是典型的原因。失败)。因此,如果您不能简单地更改密码,请先重置密码,然后重新设置密码,例如:

MembershipUser user = Membership.GetUser(sName);
if (user == null)
{
    // user not found...
    continue;
}

if (user.IsLockedOut) user.UnlockUser();
string sTemp = user.ResetPassword();

bool b = user.ChangePassword(sTemp, sPassword);
// b is false on failure

我是在控制台应用程序中完成的,所以在这种情况下,请记住将相同的system.web部分添加到其app.config中,否则密码将使用其他值进行哈希处理。

然后我将SDF重新上传到新的web.config(键必须匹配!),现在它可以工作了。旁注:在VS2010中,基于SDF的数据库通常表现得很奇怪:例如: Membership.GetUser()即使在那里存在用户名也返回null。在这种情况下,我只是获得未经修改的SDF的新副本,然后再试一次。即使关闭和重新打开VS也可能有所帮助。因此,在编辑之前,请始终保留SDF的副本...(并记住,对于控制台应用程序,它将被复制到debug / bin目录中,这是您将要使用的。)

感谢所有读者