I've got some desktop experience, but am (brand) new to web programming. I've built a well-received C# WPF desktop app that stores data in a local (on user's desktop) SqlLite DB. I'd like to transition the app to remote data storage, probably with a MS SQL Server DB, hosted by a web-host service provider. One database there would hold all the various users data, access controlled by their own username/password.
In fact I've already done that as an experiment, and it functions. My concern is security: at the moment my in-code connection string just uses my db account/password. I'm not such a newb to know that's not a good idea. There must be a standard way to move that private information out of the code and into a sort of relay between the app code and the db. But I don't know the terminology, or what to ask for, despite a day of googling. So:
(1) User requests data save, say
(2) App sends SQL statement and user credentials to relay.
(3) Relay checks credentials against db records (using my db credentials, but that's ok, they're at least not stored in the apps's source code)
(4) Assuming ok, forward sql statement to db.
Is (something like) this a thing? What's it called? Or is there some other standard way to achieve the goal of keep my connection string completely out of the code? Where do I begin reading about how to implement it? How would I know if my web-host would support such a thing?
From the point of view of web-app operations, your connection string, from your dotnet app to your RDBMS server, is considered a secret. That means it's data you retrieve from a configuration file, and is never checked in to your git or other source control system. That connection string contains your RDBMS username and password, along with stuff like the name of your database and the server where it runs.
(If you did check in an RDBMS connection string to source control for any machine other than localhost, change that password. Do it now. Cybercreeps troll github looking for connection strings to steal and use for nefarious purposes. )
Dotnet web apps have a configuration file. It's an XML file called web.config. Connection strings go into that file in an XML stanza looking like this
<configuration>
<connectionStrings>
<add name="Name"
providerName="System.Data.ProviderName"
<!-- When deploying to production,
replace this connection string with one
to connect the production data base. -->
connectionString="Valid Connection String;" />
</connectionStrings>
</configuration>
Here's some info about retrieving that kind of connection string from your dotnet program..
I've had good luck putting a globally useless locally useful localhost connection string in that file, with some xml comments explaining that it needs to be edited when putting the web app on a public server. My example shows such comments.
It's also possible to edit a connection string with the web server's IIS Manager app. This setup -- either web.config or IIS Manager -- has good security.
The scheme you outlined is more complex than you need unless, heaven forbid, every one of your customers has a different connection string.
Related
I have googled for a long time for ways to secure the SQL connection string stored in a Winforms app. Encrypting the app.config (connection string included) of a Winforms app could be useful; however, it is not as safe as a webform app since the app is installed on user's PC. Any malicious users who want find out the connection string can reverse-engineer the app using the locally saved certificate to decrypt out the connection string.
Recently, I think of a possible way for protecting my connection string.
It is like this:
I'll create a read-only user and a read-write user using MS SQL Server Management Studio. The readonly user's connection string is located in the resource properties unencrypted. It is used to connect to SQL Server and check for the login passwords into my app.
Once the password has been checked, I will call a user defined SQL function (secret key included) which input is a ciphertext and return me the connection string to login the SQL Server with the read-write user account.
Will someone view my secret key hid in the user-defined function? Will this work to protect my connection string for logging in the read-write user account?
Thanks for all your answers. After watching TimCorey's YouTube video (https://www.youtube.com/watch?v=rFncI9yfY-E), I think I am sort of knowing that my idea is too simple. Using stored procedures in a SQL server should be a safer choice than the user defined function.
Here I would like to make a summary, as suggested by Mouse Power and Charlieface, for a win-forms app to connect to a SQL server with more safety, we can get data from a SQL server either through:
(1) executing stored procedures (with limited permission) or through
(2) web APIs wherein SQL connections are made within the server.
Conventional encryption(using ASPNET_REGIIS) of connection string in web.config of a web-forms app can not be applied directly to the app.config of a winforms app. This is because the app.config and its encrypted key are both located on the client side, so it is difficult to prevent any malicious users using reverse-engineering to crack out the connection string. Nevertheless, encrypting the connection string using a key hidden somewhere (in codes, file, or resource) is still suggested, as a preliminary protection.
Using a separate account for each connection may also be an option, but this may make the programming of SQL connections relatively more complicated.
I have created a .net web application using c# that inserts, updates, and deletes data from an SQL server database. I have tested it using my localhost and it works fine. Now I would like to publish this application on a hosted site.
My question is, does the database need to be on the same server/host that the application is in for it to connect?
Does anyone have any tips on how to implement this?
No you do not have to run the Database on the same server as the application. For scalability it can be best practice to separate the two, one dedicated server for your DB and one server to host all your websites.
In your application you specify the connection to your Database. On your Database server you can also then set restrictions on the IP to access this data if you really wanted for further security.
If your Question is 'How to connect database present on another server', then you have to Add IP address of it in the Web.config file as:
<connectionStrings>
<add name="myConnectionString" connectionString="data source=myserver\SQLEXPRESS;initial catalog=myDatabase;uid=myUserName;password=myPassword;" />
</connectionStrings>
data source can be IP ADDRESS or PC NAME, where Database is stored.
does the database need to be on the same server/host that the application is in for it to connect?
It's upto you to put the Database on the same machine or a different machine.You can choose following scenarios
If it's a simple website and you only have one Machine,then you can install Database on the same server(or if'ts already present) .In this case the connection string may or may not have to change depending on what type of connection string you use(e.g if your sql server instance name is different,connection string will change)
Your website can get complex or process large amount of data,it makes sense to use a dedicated database server .This case connection string will change
Does anyone have any tips on how to implement this?
Easiest way to deal with this is using web.config transformation.All you have to do is create a new Web.Release.Config
Please refer this answer for more details How do I use Web.Config transform on my connection strings?
I have created a forms application for my project. I want to host on my website for users to download and test it. Because I am using a configuration manager I have to include the config file along with the .exe as there is a back end remote database for the application. And of course I only now realize my connection string is there for all to see. I tried renaming the app.config to web.config, but the aspnet_regiis -pef command just returns a help menu when ran as admin on my vista machine! Even if this command works and I rename web.config back to app.config, will the machine which runs the app when downloaded automatically decrypt the connection string? So in conclusion what is the best way for a novice like to approach this dilemma? Why does aspnet_regiis -pef not run? I have also looked at other posts about this topic but unfortunately they have not worked for me so far.
Either create user/specific connection string, or wrap all your data access in some web services, where you can control the autorization.
Creating user specific connection string is the simplest, but may have impact on the DB charge. You can still keep one connection string, but using windows identity to connect. In both case, you will have to spent some effort to ensure users won't able to do more than what they are allowed to do.
Wrapping your data access in web services is far more manageable but will require an extra work to make it works. Maybe you can take a look at RIA Services. The advantages are multiples: you can control the permissions within the web services, and you are reducing the exposure of unwanted queries.
Please also note that even if you encrypt the connection string in the configuration file, any malicious user will be able to decrypt it. A simple decompiler will highlight your decryption key.
You could just store an encrypt the connection string in the app.config but you will have to include the encryption key somewhere in the application. Therefore this is not safe because everyone can just decompile the application or attach a debugger and extract the connection string. Or monitor the network traffic. Actually there is now way you can prevent this from happening - whatever your application can do can be done manually by everyone (with access to the application).
The flaw in the design is that the application needs direct access to the database in the first place. It is close to impossible to ensure that the database can not be corrupted in this scenario (unless the database is only used for reading data). Essentially you would have to replicate a large portion of your business logic at the database server to ensure that no sequence of requests will corrupt the state.
A better solution would be accessing the database only indirectly through a web service. This allows you to perform better and easier to implement server-side validation and even authentication and authorization per user.
Im working in c#, I'm using mysql .net connector to interact with a remote mysql db. Is it safe to include the connection string inside the code and work with the db directly through the command object or should I be posting to a php middle layer to hide the connection string?
Thanks in advance.
In my opinion:
You shouldn't put Your connection
string directly in Your C# code if
Your application could be
decompiled = I mean WinForms application.
If You are working on a Windows
application, then try to implement a
log-in window. Where user will pass
his/her user name and password. This
solution needs a mysql user or users
for every person that would have
access to the system.
If Your are working on a web
application, then put You connection
string inside web.config file.
If You are working on application
with unrestricted access, then I
think You should implement some
layer... but remember, never pass
SQL queries as plain text via
network, as someone could sniff it.
I would recommend some kind of
webservice.
Then the connection string is just stored in the PHP middleware layer, so what's the difference? It has to be stored somewhere.
I would keep it simple and store it in the app.config or web.config of the C# app your writing.
Couple notes about storing it:
- Production connection strings should not be stored in version control.
- A production configuration file should exist on the production servers with the connection string.
- For added security, you can encrypt your connection string (http://msdn.microsoft.com/en-us/library/89211k9b(v=vs.80).aspx)
i will develop utility program for a company with more than 1000 client and the program must be win application with .Net because my program will act with another program.
What is your suggest for place of app.config?
one scenario:
We put the app.config on the server that configured once and write a windows service for it that publishes the connectionString through TCP/IP Socket.
In Socket programming we don't need for anything because we just use a free Port for send ConnectioString from server to clients. My Scenario based on this approach. (Default port embedded in app).
Reading your question (I am deciphering a bit) I can see that clients may be separated from eachother, and even if it's just in the LAN, the following solution would work:
Develop a WebService whose only job is to give the ConnectionString when called.
This enables you to have an "easy" and robust way of doing this, and could implement it only on the local intranet for security.
Regardless of this, make sure you encrypt the Data and perhaps even RSA sign it good measure. This will give you a secure, robust and less time consuming solution to your problem.
The app.config belongs with the client app - I wouldn't even try and hack together something else. Ship it as part of your app and install it. Especially the connection strings cannot really be outsourced anywhere else.
We use a hybrid scenario where we have just about only the connection string in the app.config on every client, and anything else that needs to be configured is in a database table which everyone reads.
But the connection string can't really be centralized in the database..... how would you connect to the database to read the connection string then? :-) A classic "chicken-and-egg" problem.
So: just use app.config and put your connection string there (if needed, encrypt the <connectionStrings> section).
The only viable alternative would be to embed the connection string into the app itself - as a constant string in a "Constants.cs" file or something.
Marc
The ideal architecture would be to provide a service that acts as your data layer - your WinForms application would make calls on this service to perform all its interaction with the database. Not only does this provide an abstraction layer for your data access, but it centralises your data connectivity into a single area (your data service), so you can store your connection string securely on the server that hosts this data service.
If you want central configuration, I would put the configuration into Active Directory, under the CN=Services, CN=Configuration node.
I use an adaptive connection string that configures itself based on the network and/or machine that the application is running on. I wrote a blog post about this approach some time ago. The key is to override the SettingsLoaded event to reconfigure the baked in connection strings. This will work on any .NET Windows client application or DLL. I even used this technique within DLLs to control the connection string for web applications. It really makes deployment a snap!
Of course this is not the best approach for all scenarios. One drawback is that users and administrators can't change the connection string with the configuration file.
On your server you will have IIS, you can define a url http://myapp.myserver.com and you can put an xml page there, wherever your clients can be, when they start, they can query http://myapp.myserver.com/myapp-config.xml , and on this file you can store version, connection string etc.
And you will have to manually instantiate all variables that you intend to load from this xml instead of app.config, but its not difficult to store your connection string in your program in static variable initiated after reading myapp-config.xml
Shipping app.config at client's place is not good because in case if you need to change any values, change server or distribute load, it will be difficult to redistribute everything.
Instead you can also keep a check on version of xml, if version changes, you can notify to download new version from same server and upgrade their program.