SimpleMembership MVC 4保持身份验证,但未经过身份验证

时间:2013-03-06 20:00:16

标签: authentication asp.net-mvc-4

我正在使用ASP.NET MVC 4 SimpleMembership“开箱即用”。

我在[Authorize(Roles = "User")].

的控制器上将身份验证要求设置为deco

它工作正常,除非在没有退出的情况下离开网站。下次我回来时,Request.IsAuthenticated仍然是正确的,但当我进入视图时,我得到“A network-related or instance-specific error occurred while establishing a connection to SQL.”实际上,它似乎正在尝试连接到本地数据库:{ {1}} - 在App_Data文件夹中。但我没有指向此的连接字符串,它全部在Azure Sql上。

知道这是什么吗?为什么它会假装保持登录状态?为什么尝试创建数据库?

"SQLExpress database file auto-creation error'

2 个答案:

答案 0 :(得分:0)

如果您使用SimpleMembership“开箱即用”设置,则使用Cookie来保持用户登录。 SimpleMembership首先使用EF代码,如果它不认为已存在,它将尝试创建数据库。它使用延迟加载机制,因此在您点击AccountController之前它不会尝试创建它(即您将进入登录或注册页面)。如果授权失败,您将被重定向到登录页面。如果您使用“开箱即用”设置,那么它希望使用名为DefaultConnection的web.config中的连接字符串。它看起来像这样

   <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-ProjectName-20130125152904;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-ProjectName-20130125152904.mdf" providerName="System.Data.SqlClient" />

其中ProjectName是MVC项目的名称,当您首次使用MVC 4 Internet模板创建它时。您需要将其更改为与Azure配合使用。

更新于2013年3月7日 由于您未使用默认连接字符串,因此需要更新在两个位置使用的连接字符串。你提到你在初始化程序中更新了它,所以我假设你的意思是SimpleMembershipInitializer,它的代码看起来像这样。

    public SimpleMembershipInitializer()
    {
        Database.SetInitializer<UsersContext>(null);

        try
        {
            using (var context = new UsersContext())
            {
                if (!context.Database.Exists())
                {
                    // Create the SimpleMembership database without Entity Framework migration schema
                        ((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
                }
            }

            WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
        }
        catch (Exception ex)
        {
            throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
        }

我假设(因为您没有在您的问题中提供任何代码)您更新了InitializeDatabaseConnection中的第一个参数以使用您的连接字符串的名称。这很好,但它只处理配置数据库连接。如果您查看检测数据库是否已创建并且实际创建它的代码,请在上面设置此连接。连接字符串也在UserContext中设置,您可以在AccountModels.cs中找到它。这个代码是

public UsersContext()
    : base("DefaultConnection")
{
}

如您所见,连接字符串将传递给基本上下文。如果你没有在这里更改它,那么它将使用DefaultConnection连接字符串检查是否存在并尝试创建它。我相信如果缺少连接字符串,它将尝试创建一个名为DefaultConnection的本地数据库。

如果您正在使用表单身份验证,我建议您删除初始化程序并自行处理described in this article。设计此初始化程序,以便模板生成的代码可以在开发人员不想使用表单身份验证的情况下工作。

答案 1 :(得分:0)

我终于弄清楚了这个问题!当我找到这个帖子时,我遇到了同样的问题,但由于没有明确的答案,我不得不独自探讨。

UserContext最终将失去对其连接的跟踪。通过完全绕过UserContext并避开构造函数,连接将保持稳定。

注意:我不再自动生成简单的成员资格表,所以如果是这种情况,我不确定这是否会成功。

请在此处查看AccountModels.cs中的UsersContext。您应该注释掉/删除此代码。

public class UsersContext : DbContext
{
    public UsersContext()
        : base("YourDBContext")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<webpages_Membership> webpages_Memberships { get; set; }
    public DbSet<UsersInRole> webpages_UsersInRoles { get; set; }
    public DbSet<Role> webpages_Roles { get; set; }
}

将UsersContext中的DbSets添加到您自己的上下文中:

public class YourDBContext : DbContext
{
    public DbSet<Blah> Blahs{ get; set; }
    public DbSet<Something> Somethings { get; set; }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<webpages_Membership> webpages_Memberships { get; set; }
    public DbSet<UsersInRole> webpages_UsersInRoles { get; set; }
    public DbSet<Role> webpages_Roles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }

}

当然,在完成所有操作后,您必须将对UsersContext的任何引用更改为YourDBContext,即

UsersContext uc = new UsersContext();

变为

YourDBContext ydb = new YourDBContext();

这样做的另一个好处是您不必跟踪两个不同的DBContexts。