crisco96
asked on
Trusted Connections using Membership & Role Providers
Hi,
I've developed an application using VS.NET 2.0 with the ASP.NET Membership and Role Providers. These providers use the same connection string as my application -- that is, all of the aspnet_* tables, stored procedures, etc., are in the same database beside my application's tables, stored procedures, etc.
The application uses the standard ASP.NET 2.0 controls to access the Membership and Role Providers... Login, LoginStatus, etc, are used in the aspx pages and the standard Membership.GetUser() methods (as well as other methods in the Membership class) are used in the codebeside.
This application works fine in my personal development environment, while connected to SQLEXPRESS, or any other instance of SQL Server 2000 / 2005 with a copy of my data model. However, it has come time to move the application to a live development server, and a trusted connection is required for this move. Furthermore, identity impersonate must be used without hardcoding the userName and password into the web.config file.
Here is a sample of my web.config file the way it should look in the live development environment:
<connectionStrings>
<add
name="MyConn"
connectionString="Server=M yServer;Da tabase=MyD b;Trusted_ Connection =True"
providerName="System.Data. SqlClient"
/>
</connectionStrings>
<!--[code ommitted] -->
<system.web>
<roleManager enabled="true" defaultProvider="MyProvide r">
<providers>
<clear />
<add connectionStringName="MyCo nn" applicationName="/MyApp"
name="MyProvider" type="System.Web.Security. SqlRolePro vider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d 50a3a" />
</providers>
</roleManager>
<membership
defaultProvider="MyProvide r"
userIsOnlineTimeWindow="15 ">
<providers>
<clear />
<add
name="MyProvider"
type="System.Web.Security. SqlMembers hipProvide r, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d 50a3a"
connectionStringName="MyCo nn"
applicationName="/MyAppc"
enablePasswordRetrieval="f alse"
enablePasswordReset="true"
minRequiredNonalphanumeric Characters ="0"
requiresQuestionAndAnswer= "true"
requiresUniqueEmail="true"
passwordFormat="Hashed"
passwordStrengthRegularExp ression="( ?!^[0-9]*$ )(?!^[a-zA -Z]*$)^([a -zA-Z0-9]{ 8,16})$"
/>
</providers>
</membership>
<authentication mode="Forms" />
<!--...[code ommitted]... -->
<identity impersonate="true" />
</system.web>
When moved to the live development environment, there is unexpected behavior. This application should run as the default user of the web folder where it is published to in IIS, the same user that has datareader and datawriter access to my database on the live devlopment database server. And, when this user's userName and password are hard-coded into the identity tag in web.config, that's what happens.
When the web.config file is configured as above though, I get the following error:
Server Error in 'MyApp' Application.
Login failed for user 'MYDOMAIN\WebServer$'
(I have changed the name of the user to WebServer$, but I'm told by the DBA & SysAdmins that this user is the NT Authority on the web server Below is the stack trace, which is important).
<StackTrace>
[SqlException (0x80131904): Login failed for user 'MYDOMAIN\WebServer$'.]
System.Data.SqlClient.SqlI nternalCon nection.On Error(SqlE xception exception, Boolean breakConnection) +735203
System.Data.SqlClient.TdsP arser.Thro wException AndWarning (TdsParser StateObjec t stateObj) +188
System.Data.SqlClient.TdsP arser.Run( RunBehavio r runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1838
System.Data.SqlClient.SqlI nternalCon nectionTds .CompleteL ogin(Boole an enlistOK) +33
System.Data.SqlClient.SqlI nternalCon nectionTds .OpenLogin Enlist(Sql Connection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) +628
System.Data.SqlClient.SqlI nternalCon nectionTds ..ctor(DbC onnectionP oolIdentit y identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance) +170
System.Data.SqlClient.SqlC onnectionF actory.Cre ateConnect ion(DbConn ectionOpti ons options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) +359
System.Data.ProviderBase.D bConnectio nFactory.C reatePoole dConnectio n(DbConnec tion owningConnection, DbConnectionPool pool, DbConnectionOptions options) +28
System.Data.ProviderBase.D bConnectio nPool.Crea teObject(D bConnectio n owningObject) +424
System.Data.ProviderBase.D bConnectio nPool.User CreateRequ est(DbConn ection owningObject) +66
System.Data.ProviderBase.D bConnectio nPool.GetC onnection( DbConnecti on owningObject) +496
System.Data.ProviderBase.D bConnectio nFactory.G etConnecti on(DbConne ction owningConnection) +82
System.Data.ProviderBase.D bConnectio nClosed.Op enConnecti on(DbConne ction outerConnection, DbConnectionFactory connectionFactory) +105
System.Data.SqlClient.SqlC onnection. Open() +111
System.Web.Caching.SqlCach eDependenc yAdmin.Get EnabledTab les(String connectionString) +114
[HttpException (0x80004005): Cannot get the tables enabled for SQL cache notification.]
System.Web.Caching.SqlCach eDependenc yAdmin.Get EnabledTab les(String connectionString) +401
System.Web.Caching.SqlCach eDependenc yAdmin.Get TablesEnab ledForNoti fications( String connectionString) +4
ASP.global_asax.Applicatio n_Start(Ob ject sender, EventArgs e) +164
</StackTrace>
Notice how this exception is raised from my global.asax.Application_St art() method. After commenting out all code from that method and republishing, I am able to get to the login page. After typing in a valid username and password that was added via the ASP.NET Membership Provider (to the aspnet_Users and aspnet_Membership tables) and clicking to login, I get the same error with the following stack trace:
<StackTrace>
[SqlException (0x80131904): Login failed for user 'MYDOMAIN\WebServer$'.]
System.Data.SqlClient.SqlI nternalCon nection.On Error(SqlE xception exception, Boolean breakConnection) +735203
System.Data.SqlClient.TdsP arser.Thro wException AndWarning (TdsParser StateObjec t stateObj) +188
System.Data.SqlClient.TdsP arser.Run( RunBehavio r runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1838
System.Data.SqlClient.SqlI nternalCon nectionTds .CompleteL ogin(Boole an enlistOK) +33
System.Data.SqlClient.SqlI nternalCon nectionTds .OpenLogin Enlist(Sql Connection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) +628
System.Data.SqlClient.SqlI nternalCon nectionTds ..ctor(DbC onnectionP oolIdentit y identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance) +170
System.Data.SqlClient.SqlC onnectionF actory.Cre ateConnect ion(DbConn ectionOpti ons options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) +359
System.Data.ProviderBase.D bConnectio nFactory.C reatePoole dConnectio n(DbConnec tion owningConnection, DbConnectionPool pool, DbConnectionOptions options) +28
System.Data.ProviderBase.D bConnectio nPool.Crea teObject(D bConnectio n owningObject) +424
System.Data.ProviderBase.D bConnectio nPool.User CreateRequ est(DbConn ection owningObject) +66
System.Data.ProviderBase.D bConnectio nPool.GetC onnection( DbConnecti on owningObject) +496
System.Data.ProviderBase.D bConnectio nFactory.G etConnecti on(DbConne ction owningConnection) +82
System.Data.ProviderBase.D bConnectio nClosed.Op enConnecti on(DbConne ction outerConnection, DbConnectionFactory connectionFactory) +105
System.Data.SqlClient.SqlC onnection. Open() +111
System.Web.DataAccess.SqlC onnectionH older.Open (HttpConte xt context, Boolean revertImpersonate) +84
System.Web.DataAccess.SqlC onnectionH elper.GetC onnection( String connectionString, Boolean revertImpersonation) +197
System.Web.Security.SqlMem bershipPro vider.GetU ser(String username, Boolean userIsOnline) +1491
System.Web.Security.Member ship.GetUs er(String username, Boolean userIsOnline) +81
System.Web.Security.Member ship.GetUs er(String username) +6
login.cvUserNameLookup_Ser verValidat e(Object source, ServerValidateEventArgs args) +20
System.Web.UI.WebControls. CustomVali dator.OnSe rverValida te(String value) +132
System.Web.UI.WebControls. CustomVali dator.Eval uateIsVali d() +111
System.Web.UI.WebControls. BaseValida tor.Valida te() +86
System.Web.UI.Page.Validat e(String validationGroup) +143
System.Web.UI.WebControls. Button.Rai sePostBack Event(Stri ng eventArgument) +81
System.Web.UI.WebControls. Button.Sys tem.Web.UI .IPostBack EventHandl er.RaisePo stBackEven t(String eventArgument) +7
System.Web.UI.Page.RaisePo stBackEven t(IPostBac kEventHand ler sourceControl, String eventArgument) +11
System.Web.UI.Page.RaisePo stBackEven t(NameValu eCollectio n postData) +33
System.Web.UI.Page.Process RequestMai n(Boolean includeStagesBeforeAsyncPo int, Boolean includeStagesAfterAsyncPoi nt) +5102
</StackTrace>
Before logging in the user, the method login.cvUserNameLookup_Ser verValidat e(Object, ServerValidateEventArgs) looks up the user-entered username in the databasee to make sure it exists (as a validation measure). Thus, part of this method calls Membership.GetUser(String) where String is the text entered by the user into the username text field (which is wrapped in the Value property of the ServerValidateEventArgs object).
I'm stating this because, when the overloaded Membership.GetUser() method is executed without any arguments, the same thing happens. When published to Local IIS on one of my fellow developer's computers, these same code segments trip up the same exception, however the error message indicates that login failed for user 'null'.
I really don't have any idea what's going on here. It seems like the user / process that is executing the web application is going out of scope, impersonating either NULL or the web server's NT Authority when it gets to a database call (which requires login). It also seems, sometimes, as if the application is impersonating the user logged in via the .NET 2.0 Membership Provider, which at first, is no one (can't get past the login page).
Can anyone tell me if the .NET 2.0 Membership Provider scope encompasses identity impersonate, and thus passes the currently-logged-in web application user as to the trusted connection string? If you have any questions, please post them and I will try to answer. In the meantime, I'm going to be doing some digging to see if I can isolate the problem.
Thanks!
I've developed an application using VS.NET 2.0 with the ASP.NET Membership and Role Providers. These providers use the same connection string as my application -- that is, all of the aspnet_* tables, stored procedures, etc., are in the same database beside my application's tables, stored procedures, etc.
The application uses the standard ASP.NET 2.0 controls to access the Membership and Role Providers... Login, LoginStatus, etc, are used in the aspx pages and the standard Membership.GetUser() methods (as well as other methods in the Membership class) are used in the codebeside.
This application works fine in my personal development environment, while connected to SQLEXPRESS, or any other instance of SQL Server 2000 / 2005 with a copy of my data model. However, it has come time to move the application to a live development server, and a trusted connection is required for this move. Furthermore, identity impersonate must be used without hardcoding the userName and password into the web.config file.
Here is a sample of my web.config file the way it should look in the live development environment:
<connectionStrings>
<add
name="MyConn"
connectionString="Server=M
providerName="System.Data.
/>
</connectionStrings>
<!--[code ommitted] -->
<system.web>
<roleManager enabled="true" defaultProvider="MyProvide
<providers>
<clear />
<add connectionStringName="MyCo
name="MyProvider" type="System.Web.Security.
</providers>
</roleManager>
<membership
defaultProvider="MyProvide
userIsOnlineTimeWindow="15
<providers>
<clear />
<add
name="MyProvider"
type="System.Web.Security.
connectionStringName="MyCo
applicationName="/MyAppc"
enablePasswordRetrieval="f
enablePasswordReset="true"
minRequiredNonalphanumeric
requiresQuestionAndAnswer=
requiresUniqueEmail="true"
passwordFormat="Hashed"
passwordStrengthRegularExp
/>
</providers>
</membership>
<authentication mode="Forms" />
<!--...[code ommitted]... -->
<identity impersonate="true" />
</system.web>
When moved to the live development environment, there is unexpected behavior. This application should run as the default user of the web folder where it is published to in IIS, the same user that has datareader and datawriter access to my database on the live devlopment database server. And, when this user's userName and password are hard-coded into the identity tag in web.config, that's what happens.
When the web.config file is configured as above though, I get the following error:
Server Error in 'MyApp' Application.
Login failed for user 'MYDOMAIN\WebServer$'
(I have changed the name of the user to WebServer$, but I'm told by the DBA & SysAdmins that this user is the NT Authority on the web server Below is the stack trace, which is important).
<StackTrace>
[SqlException (0x80131904): Login failed for user 'MYDOMAIN\WebServer$'.]
System.Data.SqlClient.SqlI
System.Data.SqlClient.TdsP
System.Data.SqlClient.TdsP
System.Data.SqlClient.SqlI
System.Data.SqlClient.SqlI
System.Data.SqlClient.SqlI
System.Data.SqlClient.SqlC
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.SqlClient.SqlC
System.Web.Caching.SqlCach
[HttpException (0x80004005): Cannot get the tables enabled for SQL cache notification.]
System.Web.Caching.SqlCach
System.Web.Caching.SqlCach
ASP.global_asax.Applicatio
</StackTrace>
Notice how this exception is raised from my global.asax.Application_St
<StackTrace>
[SqlException (0x80131904): Login failed for user 'MYDOMAIN\WebServer$'.]
System.Data.SqlClient.SqlI
System.Data.SqlClient.TdsP
System.Data.SqlClient.TdsP
System.Data.SqlClient.SqlI
System.Data.SqlClient.SqlI
System.Data.SqlClient.SqlI
System.Data.SqlClient.SqlC
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.ProviderBase.D
System.Data.SqlClient.SqlC
System.Web.DataAccess.SqlC
System.Web.DataAccess.SqlC
System.Web.Security.SqlMem
System.Web.Security.Member
System.Web.Security.Member
login.cvUserNameLookup_Ser
System.Web.UI.WebControls.
System.Web.UI.WebControls.
System.Web.UI.WebControls.
System.Web.UI.Page.Validat
System.Web.UI.WebControls.
System.Web.UI.WebControls.
System.Web.UI.Page.RaisePo
System.Web.UI.Page.RaisePo
System.Web.UI.Page.Process
</StackTrace>
Before logging in the user, the method login.cvUserNameLookup_Ser
I'm stating this because, when the overloaded Membership.GetUser() method is executed without any arguments, the same thing happens. When published to Local IIS on one of my fellow developer's computers, these same code segments trip up the same exception, however the error message indicates that login failed for user 'null'.
I really don't have any idea what's going on here. It seems like the user / process that is executing the web application is going out of scope, impersonating either NULL or the web server's NT Authority when it gets to a database call (which requires login). It also seems, sometimes, as if the application is impersonating the user logged in via the .NET 2.0 Membership Provider, which at first, is no one (can't get past the login page).
Can anyone tell me if the .NET 2.0 Membership Provider scope encompasses identity impersonate, and thus passes the currently-logged-in web application user as to the trusted connection string? If you have any questions, please post them and I will try to answer. In the meantime, I'm going to be doing some digging to see if I can isolate the problem.
Thanks!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.