Access .NET Membership on Live or Local provider - c#

In my web.config file I have two SQL Server connection strings, one for local and one for live:
<connectionStrings>
<remove name="LocalSqlServer" />
<add name="LocalSqlServer" connectionString="[removed]" providerName="System.Data.SqlClient"/>
<add name="LiveSqlServer" connectionString="[removed]" providerName="System.Data.SqlClient"/>
</connectionStrings>
I then have a "utils" singleton class which basically sets the connection string depending if I'm running the site on "localhost" or on my live server:
if (Environment.MachineName.ToUpper() == MyOwnConfig.GetAppSettingsValue(ConfigKeys.localhost).ToUpper()) {
this.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString();
//MembershipProvider provider = Membership.Providers["LocalAspNetMemberSqlProvider"];
//RoleProvider role = Roles.Providers["LocalAspNetMemberSqlProvider"];
}
else {
this.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["LiveSqlServer"].ToString();
//MembershipProvider provider = Membership.Providers["LiveAspNetMemberSqlProvider"];
//RoleProvider role = Roles.Providers["LiveAspNetMemberSqlProvider"];
}
My Database class then simply uses the connectionString property of my utils class. All this works fine so when I place the site locally I can then simply upload it to live without making changes to the connection strings etc in the config file and it starts using my live database.
Now I'm currently implementing "membership" into my site and for ajax for use some webmethods I'm storing the providerUserKey in a text field of the current logged in user. my web method then checks that this key is authenticated. e.g.
ajaxCreds.ajaxID1 = ((MembershipUser)Membership.GetUser()).ProviderUserKey.ToString();
QUESTION:
the question I have is How do I know if this membership is from the LIVE database or my LOCAL database. As you can see from the web config I've added in the membership/provider lines (commented out) but I don't know how to use them with the above membership.getUser() command.
Alternative... Is this a good way to go? or is it simpler to edit the web.config file when I upload to live?
Many thanks

Most people don't do it this way though I applaud you for figuring all this out. Typically, people use the deployment manager or some other build system to have a different web.config value on the server verses local.
Here is a link on changing in deployment: How do I use Web.Config transform on my connection strings?

I would suggest you to read this article:
http://blogs.msdn.com/b/schlepticons/archive/2010/07/22/modifying-asp-net-providers-at-runtime.aspx
It will show you, that also others were trying to do the similar. And this is how to succeed. Solution (if adjusted) could be similar to your needs.
put all the providers into your web.config
On App_Start adjust which will be the default (based on the Environment)
Membership API will be available as you need for Provider Key
No need to search for Provider by Name
NOTE: you have to tweak the void Application_Start(object sender, EventArgs e) implementation but the idea is there
NOTE2: What you are trying to do is definitely not exception. Configuration based on environment is pretty smart! What must be achieved is standard API usage, e.g. calls via Manager pattern
System.Web.Security.Membership
System.Web.Security.Roles
and not calls to the providers by name.

Related

Storing SQL credentials correctly

First off, this is an educational question - not something I am implementing in a productional application since I am learning the basics of C#.
Currently I have a solution containing 2 (actually 3, but one is unit testing) projects;
Form
Class Library
Inside the Class Library I have a class called Database.cs and it communicates with a MySQL database. I don't directly communicate with this Database.cs class, but other classes inside the Class Library do (for example Products.cs).
Though, I need credentials to connect to this MySQL database and I am not sure which way to go to do it safely.
Storing it inside the Class Library / hard-coding the credentials inside the class.
This wouldn't make sense to me since a user can easily grab the DLL and he technically got the credentials to the database.
Pass the credentials through the form to a class (like Products.cs) and that class passes it on while initializing the Database object
Could work, tried and it works but I am not sure if this is the 'neatest' way to do it.
Write a static class that contains properties with the credentials
Again, if I create this static class inside the Class Library I am pretty much off the same as my first example. If I would create this static class inside the Form, I require to add a reference to the Form-project from my Class Library (not the way I want it to be).
I tried looking stuff up but I am apparently not doing it right. Is there any other way to do this?
First of all never hard-code credentials into code because credentials tend to change over time so that means you will have to recompile and redeploy your application each time SQL credentials change.
Usually all information needed to connect to database is stored in application configuration file in a form of connection string.
If your application is web application then you're good to go because web.config (a web application configuration file) is stored on a web server and is never served to web requests.
But if your application is windows forms application, then security considerations kick in meaning that any user who uses your app could peek into application configuration file and get credentials. If it would be Microsoft SQL I would advise to use Windows Authentication. But with MySQL I guess you're doomed to store user name and password into connection string. Then I would suggest securing your connection string by encrypting it.
Also if your users can/have to authenticate against MySQL server (enter MySQL username and password), then you could use a connection string template and substitute certain parts of it with user name and password:
app.config
<connectionStrings>
<add name="MyApplication" connectionString="Location=myServerAddress;Data Source=myDataBase;User ID={0};Password={1};
Port=3306;Extended Properties=""""; />
</connectionStrings>
C# code
var username = textboxUsername.Text;
var password = textboxPassword.Text;
var connectionString = string.Format(ConfigurationManager.ConnectionStrings["MyApplication"].ConnectionString, username, password)
// at this point you have a connection string whitch could be passed to your Products class
Do not hardcode your credentials as that may prove to cause issues, firstly if you need to change your login credentials to the database at a later stage then you will have to recompile your class library, secondly as you mention the security will be compromised.
It is a good technique to leave the connection information to the main application instead of storing them in your data layer. Refactor your data layer to accept the connection string during runtime, this value needs to be passed by the main application to the data access layer.
This way you get 2 advantages:
When you deploy your application, the deployed location can have a different connection credential than your development environment
You can encrypt connection strings in your configuration file so as to increase security

Database Deployment issues

I'm having a hard time deploying my website.
I got through some errors and they got resolved and I successfully published my website but when I try to open any page it gives me 404 or 500 Error
My host provider told me that if this page is using a database and it's not deployed then this is might be the problem
so I tried to deploy my database and I get the connectionString error.
The problem is that I'm not storing my connectionString in the web.config
It's stored in a property in my base DAL class and it's used by all the DAL classes
so I updated it but I get the same error
I dont know what's wrong, should I include the connectionString in the web.config ?
N.B When I build the package and I try to set the active mode to 'release' it returns the setting to 'debug'!
"should I include the connectionString in the web.config ?"
Yes, your connection string should be defined in the <connectionStrings> section of the web.config for precisely this reason - so that you can easily change the setting to point to a different database environment when deploying your application to a different environment, without needing to recompile your code.
IIS recognizes your connection strings in the config file. I've seen it exposing them through the IIS management console when viewing a certain application. I had a similar problem once and it turned out it was an authentication issue. Applications on IIS run in a certain pool and under a certain user. If you specified to use windows authentication (integrated security) in your connection string then this user must have rights to access the database. If the user that runs the application doesn't have the necessary rights to connect to the database you should specify the username and password explicitly in the connection string.
In any case you can turn on includeExceptionDetailInFaults in your web.config and get a little bit more information on why your service is failing like so (msdn):
<serviceBehaviors>
<behavior>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
Assuming that your DAL is a class library, I would store the connection string in app.config. That way, you can easily change the connection string without having to put the connection string in every web application that uses the library.
"The problem is that I'm not storing my connectionString in the web.config It's stored in a property in my base DAL class and it's used by all the DAL classes so I updated it but I get the same error"
Yes, hard coding connection strings is a major problem. To answer your next question "should I include the connectionString in the web.config?", the answer is YES.
As for proper deployment of a database, you can look at this blog entry I created in 2008.
I'm sorry but all the answers advised me that I need to place the 'ConnectionString' in 'Web.config' but actually the whole problem was solved when I added my application to a virtual directory and I didn't need to change my DAL layer or add anything to the web.config
Of course I learned from your answers and I appreciate it but no I don't need to add anything in my web.config If I decided to have this design pattern.

C# ASP.net MVC database questions

I am trying to develop a website with C# ASP.net MVC. It's my first time using Visual Studio, C# and ASP.net so I have lots to learn but so far so good.
So far... I started a C# ASP.net MVC project and added a database by going to the Database Explorer and clicking "add connection". I then did some standard CRUD controllers and views.
I am at the stage where I want to implement User authentication. I'm a bit confused here. I am trying to make a custom Membership Provider. So I added it to my web.config file with the correct connection string etc.
When I run the project and go to register I get an error. "Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'."
From searching, I see lots of people have this problem and they always reference their hosting. People say this (http://weblogs.asp.net/scottgu/archive/2005/08/25/423703.aspx) is their solution but when I try pick a database I get an error. Not even sure of my server name.
So at this point I am wondering, did I set up the database right?
EDIT
Adding in a few pics to show exactly what I am doing. This is the aspnet_regsql.exe:
This is the provider with connection string, taken from an example on one of the links given.
This is my customized provider with connection string pointing to the last image.
This is a screen cap when I run the project and go to the default project Account register action:
and finally, this is the error screen when I submit
EDIT
Another update..
I sorted something out but I am not sure if it is correct. I am now getting an error when the page loads: "Invalid object name 'dbo.Tag'"
In order to solve this problem the only thing you need to do is create an application services DB. You can achieve this by running the following command from your Visual Studio Command Prompt
aspnet_regsql
Anyways it seems that your "custom provider" isn't using a custom structure for your DB, which might be the reason why you weren't expecting this error.
If you are using the default implementation, you can access to the user administration using ASP .NET Configuration, located on your project menu in visual studio.
The default implementation uses the following conn string keyword
LocalSqlServer
The are many ways of implementing the membership provider. My guess is that probably this conn string is not pointing to your aspnet services db, you could do something like this to specify a custom location for this db
<remove name="LocalSqlServer"/>
<add name="LocalSqlServer" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\aspnetdb.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" />
I made a blog post regarding this topic: How to use MembershipRole Provider and when to use custom implementations
It's hard to figure out anything from your post.
but when I try pick a database I get
an error.
You can check your server name in Surface area configuration or Sql Server Configuration Manager. If you installed Visual Studio it's probably YOUR_MACHINE_NAME\SQLEXPRESS. You can connect to it using Windows Authentication. You could also write localhost,1433 instead, but that would require enabling TCP/IP first(it's disabled by default) and setting the port number first(which in most cases is already set).

ASP.NET custom MembershipProvider

I have a client server application. The client is an asp.net c# site and the server is simply a command line application in c#. I plan on using .NET remoting to access and expose information that is on the server application and preset it to the user viewing the client.
The server application has user objects that i want to use for authentication with the asp.net login controls etc.
I implemented created a custom class "MyMembershipProvider" which implements MembershipProvider but i'm getting very confused now. What do i do next?
i know i need to update the Web.config with a "membership" node but all the examples i've seen have a reference to a connection string, mine does not need a connection string as it will not be using a database etc.
OK so i figured it out.
I don't need a connection string or anything. All i had to do was put:
<membership defaultProvider="Name of the class that you created that implements the MembershipProvider class">
<providers>
<clear/>
<add
name="Name of the class that you created that implements the MembershipProvider clas"
type="fully qualified name of the class that you created that implements the MembershipProvider class" />
</providers>
</membership>
I finally realized that the element above has to be inside the < system.web > element and that fixed it, thanks for your help.
Hope you find this article useful.
http://learn.iis.net/page.aspx/528/how-to-use-the-sample-read-only-xml-membership-and-role-providers-with-iis-70/
You need to better understand why web.config needs a certain configuration, as those database based providers have a reason to use connection strings in web.config. Then you know how to configure your provider (without a connection string as yours does not use database).

Purpose of elements having their connectionStringName set to LocalSqlServer?

1) By default configuration elements have their connectionStringName attribute set to LocalSqlServer, and as far as I know, this attribute refers to connection defined in the element in machine.config file.
a) I assume this connection string refers to database aspnetdb.mdf?!
b) I understand aspnetdb.mdf is used in cases where we don’t manually create membership or profile database ( by calling aspnet_regsql ), but I still don’t understand the purpose of configuration elements having connectionStringName attribute set to LocalSqlServer set? Namely, when and why would they need to access this database?
c) What happens if we manually set membership database via aspnet_regsql and thus don’t use aspnetdb.mdf? How will configuration elements know that we’re not using aspnetdb.mdf and thus instead try to access database we created?
2) If we wanted LocalSqlServer entry from machine.config to point to some other database file, we could do the following:
<connectionStrings>
<remove name="LocalSqlServer" />
<add name=”LocalSqlServer” ... />
</connectionStrings>
I understand that the purpose of <remove> element is to cancel any previously declared elements with same name, but in above example we simply changed the attribute of already existing connection, and as such machine.config doesn’t have two connections with same name, so why did we have to include <remove> element?
thanx
From the connectionStrings element article on MSDN:
Connection strings that are contained
in a parent configuration file are
inherited, unless the clear element is
used in the child configuration file.
The following default
connectionStrings element is
configured in the Machine.config file.
Copy Code
<connectionStrings>
<add name="LocalSqlServer" connectionString="data source=.\SQLEXPRESS;Integrated
Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User
Instance=true" providerName="System.Data.SqlClient" />
</connectionStrings>
So if that section of the config file is not modified, it automatically has that connection string.
The convention used is one of many that could have been chosen to accomplish the same task, but the people who were on the ASP.NET team at MS at the time are really the only ones who can say "why" that set of conventions was used. My understanding is that the purpose of the current configuration is to make it as easy as possible for a beginner to get started. i.e. run some wizards, automatically generate database with preconfigured settings, drag-n-drop a few security controls and they have something to work with. Since this was designed for beginners, more experienced developers run into the same set of questions that you're having now because digging into how the pieces fit together isn't simple.
One of the things you'll notice in machine.config is that all of the providers (Membership, Roles, Profile, etc) use this LocalSqlServer connection string name, which again supports the beginner scenario. Therefore, to use youur own database, you need to remove the default definition of LocalSqlServer and define your own. There isn't a replace element in the config file definition, so you have to use the remove/add sequence, which is the logical equivalent. By changing the connection string and leaving its name as LocalSqlServer, all of the providers in machine.config get pointed at your DB. This gives you the default provider definitions in for your database.
Now, if you wanted to customize the provider definitions, you could add them to your own Web.config and change their settings. At that point, you could leave LocalSqlServer as the connection string for the custom provider definitions or you could create your own connnection string and then point your custom provider definitions at your own connection string and you won't need to worry about LocalSqlServer anymore. If you remove LocalSqlServer from you web.config, you'll need to add custom provider definitions to your own web.config that reference your database string.
Hope this helps,
Joe

Categories

Resources