将MVC 4应用程序发布到azure后的身份验证问题

Mar*_*ath 9 c# asp.net-mvc forms-authentication razor azure-web-sites

我有一个基本的ASP.NET MVC 4站点,我在Azure网站上托管.身份验证是表单身份验证,尚未从默认模板进行自定义.每次我发布时,当我重新访问我的网站时,它只会挂起很长的超时(也许是几分钟),最后会向我显示错误消息.我可以通过在浏览器中删除网站的cookie并重新加载来恢复.

最初问题只是尝试访问需要身份验证的页面,但后来我将其添加到我的共享_Layout.cshtml:

@if (User.IsInRole("Admin"))
{
    <li>@Html.ActionLink("Admin", "Index", "Admin")</li>
}
Run Code Online (Sandbox Code Playgroud)

现在意味着在新发布之后根本没有页面可访问,因此我甚至无法单击注销链接,这是我以前能够解决问题的另一种方式.

我有错误的配置吗?虽然我有自己可以使用的解决方法,但在发布更新后,这对于网站用户来说不是一个好的体验.

编辑:从ELMAH日志,似乎表单身份验证尝试在我调用IsInRole时创建SQL Express数据库.我无法理解为什么会这样做,因为我的表单身份验证都设置为使用我的SQL Azure数据库.

System.Web.HttpException (0x80004005): Unable to connect to SQL Server database. ---> System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean withFailover)
   at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject, Boolean withFailover)
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at System.Web.Management.SqlServices.GetSqlConnection(String server, String user, String password, Boolean trusted, String connectionString)
ClientConnectionId:00000000-0000-0000-0000-000000000000
   at System.Web.Management.SqlServices.GetSqlConnection(String server, String user, String password, Boolean trusted, String connectionString)
   at System.Web.Management.SqlServices.SetupApplicationServices(String server, String user, String password, Boolean trusted, String connectionString, String database, String dbFileName, SqlFeatures features, Boolean install)
   at System.Web.Management.SqlServices.Install(String database, String dbFileName, String connectionString)
   at System.Web.DataAccess.SqlConnectionHelper.CreateMdfFile(String fullFileName, String dataDir, String connectionString)
   at System.Web.DataAccess.SqlConnectionHelper.EnsureSqlExpressDBFile(String connectionString)
   at System.Web.DataAccess.SqlConnectionHelper.GetConnection(String connectionString, Boolean revertImpersonation)
   at System.Web.Security.SqlRoleProvider.GetRolesForUser(String username)
   at WebMatrix.WebData.SimpleRoleProvider.GetRolesForUser(String username)
   at System.Web.Security.RolePrincipal.IsInRole(String role)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ath 9

在尝试了各种博客文章中的数十种不同建议之后,我找到了一个解决方案.将InitialiseSimpleMembership属性添加到我的家庭控制器可以解决问题.

[InitializeSimpleMembership]
public class HomeController : Controller
Run Code Online (Sandbox Code Playgroud)

在进行此更改后,我成功地管理了几个成功的发布.我怀疑原因是InitializeSimpleMembershipAttribute构造函数中的以下代码行需要在进行任何调用之前运行User.IsInRole:

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
Run Code Online (Sandbox Code Playgroud)

我想最好的办法就是跑InitializeSimpleMembership进来Application_Start.

  • 如果可行,您可能需要在web.config文件中明确连接提供程序.请参阅http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/ (2认同)