Is connecting to a database using SqlConnection() AND a Connection string safe? - c#

I am using the following code in conjunction with dapper ORM to connect to a database :
using (IDbConnection db = new SqlConnection(ConnectionString()))
{
return db.Query<object>(Sql).ToList();
}
The connection string contains database name and login information. I am wondering if while establishing connection to the database server, if any of that information could be visible to someone else.

If you mean in transit: you can force SQL Server to use encrypted connections - https://technet.microsoft.com/en-us/library/ms189067(v=sql.105).aspx
If you mean in-process - the key parts are removed by default so they won't be trivially available to other code with the SqlConnection instance; this is related to the "Persist Security Info" parameter on SqlConnection's connection-string, which defaults to false. Basically, the .ConnectionString property does not expose the credentials once provided. Note that the string will still have existed in memory at some point, so someone with raw access to the process and memory analysis tools may still be able to obtain it; see https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring(v=vs.110).aspx
However, you could also just use Windows authentication via SSPI - this then just uses the app-domain's executing user identity info to connect. Same link as above, but see the "Integrated Security" connection-string parameter.

On the Local Computer: Yes, it would be possible to get access to the information
Over the Network DB Connections: Depends on DB, SQL Server supports SSL, but if you don't use that then you'd be exposing information in your traffic

This would entirely depend on where the connection is being established from and where the connection is being established to.
If either end is in the hands of someone for example, in a distributed client, then they will be able to get hold of the connection details. Typically however, a connection is established "behind the scenes", something like from a web server to a database. Because a connection established like this is all "server side", the connection string is never visible to the "client" of the application and is therefore generally perceived to be safe - of course it is still at the mercy of the infrastructure! :)
It's worth nothing that if this is something like a thick client running on a domain then using something like Windows credentials is an option and would be as secure as the account.

Related

Check connection using Entity Framework

How can I check the database connection using Entity Framework 6?
Here's my code:
using (var context = new DatabaseDataModel(connectionString))
{
if (context.Database.Connection.State != System.Data.ConnectionState.Open)
return;
if (!context.Database.Exists())
return;
context.Items.Add(item);
}
How can I check if the connection is established before adding my items to the database? I can't open the connection because it will take plenty of time in case of corrupt connection string. That means my state check above is meaningless. The same concerns for the context.Database.Exist(), it will also take long time in case of corrupt connection string.
I aim to detect the corrupt connection string before doing any critical operation.
You want to predict if it is possible to connect to your database. Well, this is not possible. There is no way to know if you will connect until you try to. Connection to the db may fail for various reasons:
DB Server is not responding, because SqlServer is down.
The server computer is down (power failure, for example).
The server you connect to does not exist.
The server exists, but you connect on wrong port.
The database refuses connection because you are not authorized.
The db server is busy and responds very slowly.
The network is bad / busy and data is transmitted very slowly.
The server is there, but configured in such a way that it refuses your connection. For example, it wants TCP, but you try named pipes.
And many more. It is absolutely impossible to validate against all these.

Securing connection string c# ado.net connection pool

Based on the link here which talks about connection pooling I see we are creating a new SqlConnection object which takes a parameter 'connectionString'
How to use connection pool without passing the connection string? We retrieve the connection string securely but across the application we are passing around the string which makes the connection string available in memory dumps.
I am looking for a similar approach in C# way it is done in Java. We create the datasource object and ask for a connection but we do not pass around the connection string.
How to achieve the same in C# ADO.NET connection pools?
TIA
Edit: What I meant by passing around the string (this code is present in every method in database access layer):
using (SqlConnection connection = new SqlConnection($conn_string))
{
connection.Open();
// execute queries
}
If you are concerned about database credentials in memory dumps, don't use them.
Instead, you can
Use SQL Server integrated authentication
If for some reason you can't work with a domain service account, use a DSN
If you still want a factory you can use something like the EF's SqlConnectionFactory or of course write your own.

Can't connect to local SQL Server 2014 from C# using OleDbConnection

I see several answers to problems similar to mine, but I don't know enough to adapt those answers to my problem. So, with apologies for what is probably a duplicate question, here goes:
I'm trying to connect to a Microsoft SQL 2014 database on my local machine from a ASP.NET application. The code is:
oCN = new OleDbConnection(connectionString);
With a connectionString of:
Provider=SQLNCLI11; Server=FLIPPY\SQLEXPRESS; Trusted_Connection=yes;
Database=FingerTipDisplay; User Id=<my user id>; Password=<my password>
oCN is as follows after the call to new OleDbConnection():
- oCN {System.Data.OleDb.OleDbConnection} System.Data.OleDb.OleDbConnection
CanRaiseEvents true bool
ConnectionString "Provider=SQLNCLI11; Server=FLIPPY\\SQLEXPRESS; Trusted_Connection=yes; Database=FingerTipDisplay; User Id=<my user id>; Password=<my password>" string
ConnectionTimeout 15 int
Container null System.ComponentModel.IContainer
DataSource "" string
Database "" string
DbProviderFactory null System.Data.Common.DbProviderFactory
DesignMode false bool
+ Events {System.ComponentModel.EventHandlerList} System.ComponentModel.EventHandlerList
Provider "SQLNCLI11" string
+ ServerVersion 'oCN.ServerVersion' threw an exception of type 'System.InvalidOperationException' string {System.InvalidOperationException}
Site null System.ComponentModel.ISite
State Closed System.Data.ConnectionState
+ Static members
+ Non-Public members
I believe my SQL server is running correctly:
I can't get SQL Server Agent to start, and am not sure if that's causing my problem or not. From other replies I've ensured TCP/IP is enabled:
This is my database structure:
and I think that the user name and password I'm connecting has the right permissions from the dbo schema:
I've checked the SQL Server logs and don't see anything that looks like a failed login attempt, and I don't know where to look in the OleDbConnection object for feedback on why the connection failed. I'm working on someone else's code, so I'm reluctant to use SqlConnection() since I don't know the implications for the rest of the app.
I'm guessing that the problem is in the connection string, but I don't know what to use for that. I've tried SQLOLEDB as the provider, and I've tried using Initial Catalog instead of Database.
Thanks in advance for your help.
Update:
Thanks for all the help so far. oCN.Open() was throwing an OleDbException immediately, and it was:
"Login failed for user 'riehlj2002#gmail.com'."
I made some changes to the connection string based on the advice below...this is what it looks like right now:
Provider=SQLNCLI11; server=localhost; DataSource=localhost\SQLEXPRESS; Database=FingerTipDisplay; user id=<my user id>; password=<my password>
Now it doesn't throw the exception right away, but it still throws it. This is the exception I get:
{"Login timeout expired\r\nA network-related or instance-specific error has occurred while establishing a connection to SQL Server. Server is not found or not accessible. Check if instance name is correct and if SQL Server is configured to allow remote connections. For more information see SQL Server Books Online.\r\nNamed Pipes Provider: Could not open a connection to SQL Server [2]. \r\nInvalid connection string attribute"}
A few things I notice.
First, if I change server to localhost\SQLEXPRESS I get an immediate exception telling me that I have an invalid connection string attribute, so the advice in this link doesn't work for me.
Second, it doesn't seem to matter whether I use localhost or my machine name...it does the same thing.
Third, I was surprised to see something in there about the named pipes protocol. I went into the SQL Server Configuration Manager and enabled that protocol...it didn't make a difference.
Fourth, it doesn't make a difference whether I specify DataSource or not in terms of the exception, but intuitively it seems like I have to specify the server instance somewhere so I've left it in.
Fifth, if I change the provider to SQLOLEDB I get a different exception: {"[DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied.\r\nInvalid connection string attribute"}, so I think I'm on the right track with SQLNCLI11.
Sixth, in the OleDbConnection object the DataSource and Database properties are both empty strings despite their being specified in the connection string.
Finally, the very last part of the exception I'm getting now talks about an invalid connection string attribute, but I removed each one in turn and either got the same exception or got another one that I've already described.
Again, thanks for the help.
You are using Trusted_Connection=yes but specifying a username and password. It's either one or the other, I don't think you can do both in the same connection string (not sure if that'd raise any errors, but the supplied user and password would be at least ignored, for sure).
In your case, since you are using a user and a password, you'd need to set Trusted_Connection to no (or false), or just not set it (it should be false by default)
OK, I found the problem. My original connection string wasn't finding the database, so I got no additional information in the server logs. I changed the connection string to:
Provider=SQLNCLI11; server=localhost\SQLEXPRESS; Database=FingerTipDisplay; user id=<my user id>; password=<my user id>
And then I found in the server log that it was configured to use Windows authentication only. I used this link to allow SQL server authentication, and all is now well. Your answers got me going in the right direction...thanks.

Data source for connection string

What connection string should I use if SSMS connects to it using simply machine name, without instance name?
I mean it connects using the following string: PCName
I used to connect using PCName/SQLExpress. I cannot set correct connection string in my app in order to connect app to database on this machine.
How can I check what data source I should use? I've checked in Sql Server configuration that server instance named as SQLEXPRESS.
So I tried data source as:
.\SQLEXPRESS
PCName\SQLEXPRESS
.
I'm trying to connect to a service-based database, located in my app folder. So I'm using the following connection string:
data source=PCName;attachdbfilename=|DataDirectory|\spareparts.mdf;integrated security=true;user instance=true;multipleactiveresultsets=true;App=EntityFramework;
If SSMS connects via PCName then your application should be able to use Data Source=PCName. However it depends on whether your application is on the same machine as SSMS or not. If on a different machine it might not be able to connect for a variety of reasons. We can't speculate what the problem might be if all you do to describe the issue is "It won't connect" - what does that mean? Do you get an error message? If so, what is it? Make sure:
SQL Browser service is started
TCP/IP is enabled
Add Network=DBMSSOCN; to the connection string
You've also tried the IP address in addition to PCName
Firewall isn't blocking the SQL Server port

Solving a timeout error for SQL query

I am getting this error:
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
I know there are already guides out there to help solve this but they are not working for me. What am I missing or where should I add the code to these SQL statements in my C# program:
String sql = project1.Properties.Resources.myQueryData;
SqlDataAdapter sqlClearQuestDefects = new SqlDataAdapter(sql,
"Data Source=ab;Initial Catalog=ac;User ID=ad; Password =aa");
DataSet lPlanViewData = new DataSet();
sqlClearQuestDefects.Fill(lPlanViewData, "PlanViewData");
I am getting the timeout error at this line:
SqlDataAdapter sqlClearQuestDefects = new SqlDataAdapter(sql,
"Data Source=ab;Initial Catalog=ac;User ID=ad; Password =aa");
SqlDataAdapter adp = new SqlDataAdapter();
adp.SelectCommand.CommandTimeout = 0; // Set the Time out on the Command Object
You're trying to connect to a SQL Server, and it is taking longer than ADO.NET is willing to wait.
Try connecting to the same server, using the same username and password, using SQL Server Management Studio. If you get the same error, there is either something wrong with your connection string, the server you specify is not running, or you can't get to the server across the network from where you are (maybe you're on a public IP address trying to get in to an internal server name). I can't think of a scenario in which you'd enter the exact same server and credentials into SSMS and connect, then do the same in ADO.NET and fail.
If you're on a slow network, you can try increasing the timeout value. However, if a connection is going to happen at all, it should happen pretty quickly.
Take a look at both your SQL Native Client settings, and the SQL Server settings on the server. There is a section for allowed protocols; SQL can connect using a variety of protocols. Usually, you want TCP/IP for a server on the network, and Named Pipes for a server running on your own computer.
EDIT FROM YOUR COMMENT: Oh, that's normal; happens all the time. From time to time on a TCP network, packets "collide", or are "lost" in transmission. It's a known weakness of packet-switching technologies, which is managed by the TCP protocol itself in most cases. One case in which it isn't easily detected is when the initial request for a connection is lost in the shuffle. In that case, the server doesn't know there was a request, and the client didn't know their request wasn't received. So, all the client can do is give up.
To make your program more robust, all you have to do is expect a failure or two, and simply re-try your request. Here's a basic algorithm to do that:
SqlDataAdapter sqlClearQuestDefects;
short retries = 0;
while(true)
{
try
{
sqlClearQuestDefects = new SqlDataAdapter(sql, "Data Source=ab;Initial Catalog=ac;User ID=ad; Password =aa");
break;
}
catch(Exception)
{
retries++;
//will try a total of three times before giving up
if(retries >2) throw;
}
}
Since the exact command to increase connection time out wasn't mentioned in the other answers (of yet)- if you do determine a need to increase your connection time out, you would do so in your connection string as follows:
Data Source=ab;Initial Catalog=ac;User ID=ad; Password =aa; Connection Timeout=120
Where 120 = 120 seconds. Default is 20 or 30 as I recall.
This is probably a connection issue with your database, for example if you had the following connection string:
"Data Source=MyDatabaseServer...
Then you need to make sure that:
The machine MyDatabaseServer is connected to the network and is accessible from the machine you are running your application from (under the name "MyDatabaseServer")
The database server is running on MyDatabaseServer
The database server on MyDatabaseServer is configured to accept connections from remote machines
The firewall settings both on the local machine and MyDatabaseServer are correctly set up to allow SQL Server connections through
Your username / password etc... are correct
You can also try connecting to the given database instance using SQL Server Management Studio from the client machine as a diagnosis step.
There are plenty of articles that address SQL Server connectivity issues - do a Google search for the specific error message that comes up or failing that as a specific question on Server Fault
Faced this problem recently and found the resolution that worked for me.
By the way, setting Timeout = 0 helped to avoid the exception, but the execution time was unreasonable, while manual execution of the store procedure took a few seconds.
Bottom line:
I added SET IMPLICIT_TRANSACTIONS OFF to the stored procedure that is used to fill the data set.
From MSDN:
The SQL Server Native Client OLE DB Provider for SQL Server and the
SQL Server Native Client ODBC driver automatically set
IMPLICIT_TRANSACTIONS to OFF when connecting. SET
IMPLICIT_TRANSACTIONS defaults to OFF for connections with the
SQLClient managed provider, and for SOAP requests received through
HTTP endpoints.
[...]
When SET ANSI_DEFAULTS is ON, SET IMPLICIT_TRANSACTIONS is ON.
So I believe that in my case defaults weren't as required. (I couldn't check that. Don't have enough privileges on SQL server). But adding this line to my SP solved the problem.
IMPORTANT: In my case I didn't need the transaction, so I had no problem to cancel the implicit transaction setting. If in your case transaction is a must you, probably, shouldn't use this solution.

Categories

Resources