Membership.ApplicationName and thread safety.

M

MrGrundh

Membership.ApplicationName and thread safety

I have developed an ASP.NET 2.0 application that uses
AspNetSqlMembershipProvider. When the user logging in he/she also enters
Membership.ApplicationName that i use in the event OnLoggingIn.

Protected Sub OnLoggingIn(ByVal sender As Object, ByVal e As
System.Web.UI.WebControls.LoginCancelEventArgs)

Membership.ApplicationName = TextboxApplicationName.Text

End sub

This works fine! But i read that the Membership.ApplicationName is not
thread safe. Could this be a problem and how do you solve it?

Thanks in advance!
 
S

Steven Cheng[MSFT]

Hello MrGrundh,

As for the "Membership.ApplicationName" property, it does be an read/writer
property and is not threadsafe ( can be accessed by concurrent threads).
Actually this property is associated with the underlying MembershipProvider
instance(SqlMembershipProvider, your custom membershipprovider ....) which
is configured and used in your ASP.NET application. When you change this
property, you're actually changing the property on the underlying
membershipProvider instance.

From the document of this property below:

=========================
Because a single default membership provider instance is used for all of
the requests served by an HttpApplication object, you can have multiple
requests executing concurrently and attempting to set the ApplicationName
property value. The ApplicationName property is not thread safe for
multiple writes, and changing the ApplicationName property value can result
in unexpected behavior for multiple users of an application. We recommend
that you avoid writing code that allows users to set the ApplicationName
property, unless you must. An example of an application where setting the
ApplicationName property may be required is an administrative application
that manages membership data for multiple applications. Such an application
should be a single-user application and not a Web application.
==========================

#Membership.ApplicationName Property
http://msdn2.microsoft.com/en-us/library/system.web.security.membership.appl
icationname.aspx

We can find that this property should be constant for a single provider
instance during the applciation's lifecycle , but only configured at
intilization time. In other words, you should configure it either in
web.config for the provider or at an initialize period(such as
Application_Start) in the application. The only scenario we should change
it in application code is that we're developing an Application
administrative interface which need to manage users in multiple application.

So what's the detailed application logic in your case? Are you developing
an administrative interface which manage users in multiple application or
you just have limited number of applications to separate different group of
users?

If you do need to manage membership users across multiple
applications(different applicationName) and your application will be
accessed by concurrent users, a recommended way is to configure a separate
provider for each application and use them respectively.

For example, you can add the following two providers in web.config for two
applications:

<add name="myApp1" type="System.Web.Security.SqlMembershipProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
applicationName="myApp1"
........................" />

<add name="myApp2" type="System.Web.Security.SqlMembershipProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
applicationName="myApp2"
........................" />


Then, in your application's code you can use the below code to manipulate
users in the specified application:

=========================
string appname = txtAppName.Text;

MembershipProvider membership = Membership.Providers[appname];

if (membership != null)
{
membership.CreateUser(....)
}
else
{
//invalid application name
}
=====================


Please feel free to let me know if you have any further questions on this.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

MrGrundh

Thank you Mr Cheng!

In our application the companies can add user themself and we belives that
if company1 adds a simple declared user like bjorn with password bjorn123 its
easy for users on company2 by misstake logging in on company1 site. So as an
extra protection we want to use sepparate applicationnames.


Steven Cheng said:
Hello MrGrundh,

As for the "Membership.ApplicationName" property, it does be an read/writer
property and is not threadsafe ( can be accessed by concurrent threads).
Actually this property is associated with the underlying MembershipProvider
instance(SqlMembershipProvider, your custom membershipprovider ....) which
is configured and used in your ASP.NET application. When you change this
property, you're actually changing the property on the underlying
membershipProvider instance.

From the document of this property below:

=========================
Because a single default membership provider instance is used for all of
the requests served by an HttpApplication object, you can have multiple
requests executing concurrently and attempting to set the ApplicationName
property value. The ApplicationName property is not thread safe for
multiple writes, and changing the ApplicationName property value can result
in unexpected behavior for multiple users of an application. We recommend
that you avoid writing code that allows users to set the ApplicationName
property, unless you must. An example of an application where setting the
ApplicationName property may be required is an administrative application
that manages membership data for multiple applications. Such an application
should be a single-user application and not a Web application.
==========================

#Membership.ApplicationName Property
http://msdn2.microsoft.com/en-us/library/system.web.security.membership.appl
icationname.aspx

We can find that this property should be constant for a single provider
instance during the applciation's lifecycle , but only configured at
intilization time. In other words, you should configure it either in
web.config for the provider or at an initialize period(such as
Application_Start) in the application. The only scenario we should change
it in application code is that we're developing an Application
administrative interface which need to manage users in multiple application.

So what's the detailed application logic in your case? Are you developing
an administrative interface which manage users in multiple application or
you just have limited number of applications to separate different group of
users?

If you do need to manage membership users across multiple
applications(different applicationName) and your application will be
accessed by concurrent users, a recommended way is to configure a separate
provider for each application and use them respectively.

For example, you can add the following two providers in web.config for two
applications:

<add name="myApp1" type="System.Web.Security.SqlMembershipProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
applicationName="myApp1"
........................" />

<add name="myApp2" type="System.Web.Security.SqlMembershipProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
applicationName="myApp2"
........................" />


Then, in your application's code you can use the below code to manipulate
users in the specified application:

=========================
string appname = txtAppName.Text;

MembershipProvider membership = Membership.Providers[appname];

if (membership != null)
{
membership.CreateUser(....)
}
else
{
//invalid application name
}
=====================


Please feel free to let me know if you have any further questions on this.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Steven Cheng[MSFT]

Thanks for your reply MrGrundh,

Then, how many companies will be involved in your application, if the
number is not two large, you can consider the approach in my last reply.

If there is any further questions or problem , please feel free to post
here.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

MrGrundh

There are about 20 companies involved at the moment so your approach will
work. Where do i put the logic for validate the user? In OnLoggingIn event?

Thank you in advance!
 
S

Steven Cheng[MSFT]

Hi MrGrundh,

Yes, since the LoginControl will always use the default provider, we need
to programmtically do the authentication/validate user here. And I think
"OnLoggingIn " event is a workable one if you still want to make use of the
login control as the login user interface.

Please feel free to let me know if there is anything else you wonder.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Steven Cheng[MSFT]

Hi MrGrundh,

Just want to check whether you've got it working or still have any question
on this? If you need any further help, please feel free to post here.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

MrGrundh

H Mr Cheng!

Thank you for your help! I think your solution will work, but havn't tried
it in our production environment yet.
 
S

Steven Cheng[MSFT]

Thanks for the quick reply MrGrundh,

That's all right. Please feel free to let me know if you need any further
help at your convenience.

Good luck!

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead

This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

MrGrundh

Dear Mr Cheng!

How do i add a user to a role if i have mupltiple providers?

It is not possible to use the built in roles.AddUserToRole because it only
uses username and rolename in clear text. So if i have the same username in
two or more membershipproviders it wont work.

Thanks in advance!
 
S

Steven Cheng[MSFT]

Hi MrGrundh,

Nice to hear from you and sorry for the delay response.

As for the System.Web.Security.Roles class you mentioned, it actually call
the Roles.Provider to perform any role management operations. And the
"Provider" property refer to the default RoleProvider configured for the
ASP.NET application. Just like the membership provider, ASP.NET 2.0
configure the SqlRoleProvider as the default role provider. We can also use
the following web.config section to override or define our custom role
providers:

==================

<roleManager defaultProvider="NewAspNetSqlRoleProvider">
<providers>
<add name="NewAspNetSqlRoleProvider"
connectionStringName="LocalSqlServer"
applicationName="MyApplication"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

</providers>
</roleManager>

=====================

As you can see, the roleprovider also contains a "ApplicationName" which
determine the application in which the role we'll manage.

so for your application, the question here is whether you'll manage the
roles for users in different membership providers(different applications )
together or separate them(each membership application's user will have
their own roles in each application)?

**if you will let those users in different applications share the same
roles, you can just define the single roleProvider or just the default one
and do not need to explicitly set ApplicationName for the role provider.

**if you want each Application has its own roles, you can just define
multiple RoleProviders in the <providers> section above, and then, use the
following code to locate the certain provider according to the
ApplicationName of the certain user:

==========
RoleProvider provider = Roles.Providers["ApplicationName"];
provider.AddUsersToRoles(....)
==========

Hope this helps.

Actually, most of the new services in ASP.NET 2.0 adopt the provider-based
model which is convenient for us to manage them in configuration file.

You can find more info about providers in ASP.NET 2.0 in the following site:

#Provider Toolkit
http://msdn.microsoft.com/asp.net/downloads/providers/default.aspx


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

MrGrundh

Hi mr Cheng!

The suggested solution will not work because the method Roles.AddUserToRole
only accepts username and role as input and not users ID (guid)

Roles.AddUserToRole(CreateUserWizard1.UserName, "Friends")

We want to ONE roleprovider and multiple membershipproviders. The problem is
when we have the same username in different membershipproviders and want to
add the user to a role.

Scenario:

-A User (admin) logges in to membershipprovider1 and creates user "bjorn"
and add him to role "Friends". That works alright.

-A User (admin) logges in to membershipprovider2 and creates user "bjorn"
and add him to role "Friends". You got an error that says "The user 'bjorn'
is already in role 'Friends'.".

Web.Config RoleProvider:

<roleManager defaultProvider="MyAspNetSqlRoleProvider"
enabled="true"
cacheRolesInCookie="true"
cookieName=".ASPROLES"
cookieTimeout="30"
cookiePath="/"
cookieRequireSSL="false"
cookieSlidingExpiration="true"
cookieProtection="All">
<providers>
<clear/>
<add name="MyAspNetSqlRoleProvider"
connectionStringName="LocalSqlServer"
applicationName="/MyRoles"
type="System.Web.Security.SqlRoleProvider"/>
</providers>
</roleManager>


Web.Config MembershipProvider:

<membership>
<providers>
<clear />
<add connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="true"
applicationName="/" requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="5"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider" />
<add connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true" requiresQuestionAndAnswer="true"
applicationName="/MoreFriends" requiresUniqueEmail="false"
passwordFormat="Hashed" maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="5"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" name="MoreFriends"
type="System.Web.Security.SqlMembershipProvider" />
</providers>
</membership>

Sample code for create user:

Protected Sub CreateUserWizard1_CreatingUser(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.LoginCancelEventArgs) Handles
CreateUserWizard1.CreatingUser

Dim myNewUser As MembershipUser
Dim status As System.Web.Security.MembershipCreateStatus
' Get the correct membershipprovider for the user.
Dim myMembership As MembershipProvider =
Membership.Providers(Session.Item("ApplicationName"))
myNewUser = myMembership.CreateUser(CreateUserWizard1.UserName,
CreateUserWizard1.Password, CreateUserWizard1.Email,
CreateUserWizard1.Question, CreateUserWizard1.Answer, True, Nothing, status)

' Add the created user to the role Friends.
Roles.AddUserToRole(CreateUserWizard1.UserName, "Friends")
e.Cancel = True

End Sub


Steven Cheng said:
Hi MrGrundh,

Nice to hear from you and sorry for the delay response.

As for the System.Web.Security.Roles class you mentioned, it actually call
the Roles.Provider to perform any role management operations. And the
"Provider" property refer to the default RoleProvider configured for the
ASP.NET application. Just like the membership provider, ASP.NET 2.0
configure the SqlRoleProvider as the default role provider. We can also use
the following web.config section to override or define our custom role
providers:

==================

<roleManager defaultProvider="NewAspNetSqlRoleProvider">
<providers>
<add name="NewAspNetSqlRoleProvider"
connectionStringName="LocalSqlServer"
applicationName="MyApplication"
type="System.Web.Security.SqlRoleProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

</providers>
</roleManager>

=====================

As you can see, the roleprovider also contains a "ApplicationName" which
determine the application in which the role we'll manage.

so for your application, the question here is whether you'll manage the
roles for users in different membership providers(different applications )
together or separate them(each membership application's user will have
their own roles in each application)?

**if you will let those users in different applications share the same
roles, you can just define the single roleProvider or just the default one
and do not need to explicitly set ApplicationName for the role provider.

**if you want each Application has its own roles, you can just define
multiple RoleProviders in the <providers> section above, and then, use the
following code to locate the certain provider according to the
ApplicationName of the certain user:

==========
RoleProvider provider = Roles.Providers["ApplicationName"];
provider.AddUsersToRoles(....)
==========

Hope this helps.

Actually, most of the new services in ASP.NET 2.0 adopt the provider-based
model which is convenient for us to manage them in configuration file.

You can find more info about providers in ASP.NET 2.0 in the following site:

#Provider Toolkit
http://msdn.microsoft.com/asp.net/downloads/providers/default.aspx


Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.

==================================================



This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Steven Cheng[MSFT]

Thanks for your reply MrGrundh,

After your further description, I think you're right. A single role
provider with multiple membership user providers will not work here,
especially when you want to utilize the declarative role based
authorization in the web application.

When we use single RoleProvider, it always use the fixed applicationName
(configured in the provider configuration in web.config) and when we add
user into a role, it always assume the user is also in this applicationName
and will not add additional information to distince users in different
application.

So far I haven't found any perfect means on this. What we can get is as
below:

** if still use single provider to store roles for multiple application,
we'll not be able to handle duplicaetd usernames (in different application)
scenario.

** if use multiple role providers, there won't have user/role collision
issue, however, in such case, we will need to explicitly use the correct
role provider (according to applicationName) programmtically and lose the
declarative role based authroization feature (since ASP.NET role based
authorization only use the default role provider).

Actually this is also due to the limitation of the membership/role
provider, they're originally designed for manipulating users/roles in a
single application only and for your scenario, it is a bit beyond the
built-in ability.

Anyway, please feel free to let me know your consideration or if you have
any other questions on this.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
K

krs

Hi Steven,

I have a question on the same subject if you dont mind?

W have an asp.net 2.0 application. The way we have written this web app is
that many companies can use the same software, differing by sub-domain. So if
we setup companyA.software.com they are company id 123, if we setup another
companyB.software.com they are company id 345. The application identifies the
sub-domain requested and set's the company id accordingly. This works well.

We also have used asp.net 2.0 membership in this application. We needed to
ensure that users are unique within each company, we did this by in
session_start setting the Membership.applicationName and
Roles.ApplicationName, similar to how we set the company id based on the url.
We 've found that this does not work and see from this thread that this is
due to a threading issue - we found that changing this resulted in other
users being 'kicked' out to the login screen. We are now trying to find a
solution to this problem...

We considered prefixing the usernames with the company id as they are added,
so for example '345~BobSmith' so that all users are unique to a company. This
seemed to work until we found that email addresses for users would not be
unique this way.

Your suggestion of having different providers in the web.config I dont think
will work in this scenario as we may have many different companies and we
would need to change the web.config on the fly, restarting the application
every time a new user signs up.

Do you have any other potential suggestions that we could consider for this
problem?

Many Thanks!
Kieran
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top