Similar but not the same:
How to securely store database connection details
Securely connecting to database within a application
Hi all, I have a C# WinForms application connecting to a database server. The database connection string, including a generic user/pass, is placed in a NHibernate configuration file, which lies in the same directory as the exe file.
Now I have this issue: The user that runs the application should not get to know the username/password of the general database user because I don't want him to rummage around in the database directly.
Alternatively I could hardcode the connection string, which is bad because the administrator must be able to change it if the database is moved or if he wants to switch between dev/test/prod environments.
So long I've found three possibilities:
The first referenced question was generally answered by making the file only readable for the user that runs the application.
But that's not not enough in my case (the user running the application is a person. The database user/pass are general and shouldn't even be accessible by the person.)
The first answer additionally proposed to encrypt the connection data before writing it to the file.
With this approach, the administrator is not able anymore to configure the connection string because he cannot encrypt it by hand.
The second referenced question provides an approach for this very scenario but it seems very complicated.
My questions to you:
This is a very general issue, so isn't there any general "how-to-do-it" way, somehow a "design pattern"?
Is there some support in .NET's config infrastructure?
(optional, maybe out of scope) Can I combine that easily with the NHibernate configuration mechanism?
Update:
In response to the first answers: There are several reasons why I would want to connect to the database directly and not use a web service:
(N)Hibernate can only be used with a database, not webservices (am I right?)
We plan to provide offline capability, i.e. if the database or network should be down, the user can continue his work. To manage this, I'm thinking of having a local, in-proc database, e.g. SQL Server Compact, and using MS Sync framework to synchronize it with the server database as soon as it is up again.
Do you have any further ideas taking this into account?
First of all, letting untrusted users connect to a database is generally not a good idea. So many things can go wrong. Put a web service inbetween.
If you absolutely have to do it, make it so that it doesn't matter even if they get the username and password. Limit their privileges in the database so that they can only execute a few stored procedures that have built-in security checks.
Whatever you do, you can't give the username/password of a privileged user to an untrusted person. It's just asking for trouble. No matter how well you try to hide your credentials within an encrypted string inside a binary file or whatnot, there's always a way to find them out. Of course whether anyone'll actually do it depends on how interesting your data is, but silently hoping that mean people with debuggers will just leave you alone is not a very good security measure.
Actually the WebService approach (mentioned in some other answer) means that you move NHibernate and its logic to the web-service. The WebService then, exposes the db functionality available to the application using the WebService's methods.
There is practically only one user for the database, the one the WebService uses and if you want the application user to have different db privileges you abstract it from the WebService layer
In the end, the WinForms application is only aware of the location of the WebService where it requests data through the WebService's methods and you can apply any required security measure between these two endpoints.
For off-line capability it all boils down to making a secure way to persist your data to local storage and providing a synchronization method via the WebService
I have actually done this using a webservice that communicated with the DB and a WinForm application (.NET Compact Framework) that only talked to the webservice and in case of no cellular network coverage it would serialize the changes to the memory card (the data was not important so for my case obscure/obscene security measures where not taken)
UPDATE with a small example as requested (i do find it strange though to ask for an example on this)
you have set up your domain classes and nhibernate configuration and (for example) your repository stuff in a project of type ASP.NET WebService Application. For the sake of simplicity i'm only going to have a single web-service class Foo (in Foo.asmx.cs) and well as a single Bar domain class
so you get this (actual implementation varies):
namespace FWS
{
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class FooService : WebService
{
private readonly ILog errorLogger = LogManager.GetLogger("ErrorRollingLogFileAppender");
private readonly IDaoFactory daoFactory = new DaoFactory();
private readonly ISession nhSession = HibernateSessionManager.Instance.GetSession();
}
[WebMethod]
public Bar[] GetFavoriteBars(string someParam, int? onceMore){
return daoFactory.GetBarDao().GetFavoriteBars(someParam, onceMore); //returns a Bar[]
}
}
and we abstract the daobehaviour, or just use the nhsession directly, exposed as a webmethod.
Now from the WinForm application all you need to do is Add a WebReference which makes all necessary changes to configuration but also generates all necessary classes (in this example, it will create a Bar class as the web-service exposes it).
namespace WinFormK
{
public class KForm(): System.Windows.Forms.Form
{
public void Do()
{
var service = new FWS.FooService();
string filePath = "C:\\temp\FooData.xml";
Bar[] fetched = service.GetFavoriteBars("yes!", null);
//lets write this to local storage
var frosties = new XmlSerializer(typeof(Bar));
TextReader reader = new StreamReader(filePath);
try
{
var persisted = (T)frosties.Deserialize(reader);
}
catch(InvalidOperationException)
{
//spock, do something
}
finally
{
reader.Close();
reader.Dispose();
}
}
}
}
there are certain things you have to take note to:
You essentially lose lazy stuff, or at least you lose it in your winform application. The XML serializer cannot serialize proxies and as such you either turn of lazy fetching on those collections/properties or you use the [XmlIgnore] attribute which in turn do what it implies on serialization.
You cannot return interfaces on the WebMethod signatures. They have to be concrete classes. So, returning IList<Bar> will have to be transformed to List<Bar> or something of the like
The webservice is executed by IIS and is visible from a web browser. By default, only local browser requests will be served (but that can be changed) so you can test your data access layer separately of what your winform does.
The receiving end (winform app) has no knowledge of NHibernate whatsoever.
In the example above i've kept the same name for the dao-methods for the web-methods; As long as you didn't keep nhibernate--specific methods in your dao's (lets say like a NHibernate.Criterions.Order parameter) you will probably find no problem. In fact you can have as many .asmx classes in your webservice as you want, probably even 'map' them to the corresponding dao's (like public class FooService : WebService, public class BarService : WebService, public class CheService : WebService where each corresponds to a DAO).
You will probably have to write some kind of polling method between your endpoints to keep your presented data fresh.
WebService data is verbose; extremely so. It is advisable to zip them or something before sending them over the wire (and maybe encrypt them as well)
the win application only knows a configuration entry: http://server/FWS/FooService.asmx
Webservices have Session disabled by default. remember that before starting using the session for user data.
You will probably have to write some kind of authentication for the webservice
In the example above i am returning a Bar[] with Bar being mapped with nhibernate. More often than not this may not be the case and you may be required to write an auxiliary class WSBar where it adapts the original Bar class to what the webservice and the winform application can consume. This class is actually just a data carrier. Again this depends on how much integration exists with your domain classes and nhibernate as well as how muxh complicated your classes are: Certain data structures cannot be serialized by default.
This model may not suit what you have already done with your application
I think it's hard to do : it's like you don't want a user of stackoverflow to know his password.
A user can always trace his network traffic and see the user/password (you can had an encoding, but it still won't be 100% sure I think).
I think that you should add a webservice between your user and your database with a unique id for each user.
This is why database desktop apps suck. There is no good way to slice it. Best bet would be to use stored procedures or web services. Basically, another layer that can be locked down and control access to the database.
Related
Background
I'm building a two-tiered C# .net application:
Tier 1: Winforms client application using the MVP (Model-View-Presenter) design pattern.
Tier 2: WebAPI RESTful service sitting on top of Entity Framework and SQL Server.
If you would like more detail on the application I'm building, I gave a probably too thorough explanation here.
Current Development
Currently, I'm working on the Winforms client. Particularly, I'm trying to hash out a adequate implementation of the command pattern within this client. I was fortunate enough to stumble across this excellent blog post that outlines a solid command architecture. To complement that post, the author followed up by explaining how he separates queries from commands. After reading those blogs, it becomes very clear that my tier 2 (web api service) would greatly benefit from implementing both of these. The generic implementation allows for fantastic flexibility, testability, and extensibility.
Question
What is less clear to me is how I go about implementing these patterns on the winforms client side of things (tier 1). Do queries and commands continue to be considered separate here? Consider a basic action, such as a login attempt. Is that a query or a command? Ultimately, you need data back (user information on the server) from the web service, so that would make me think it is a query. What about another case, such as a request to create a new user. I understand that you would create a command object that stores the user information and send that off to the service. Commands are supposed to be fire and forget, but wouldn't you want some sort of confirmation from the service that the command was successful? Furthermore, if a command handler returns void, how would you tell the presenter whether or not the user creation request was successful?
At the end of the day, for any given UI task (say the user creation request), does it end up that you end up having a winforms client based query/command, as well as a web api service version of the command/query which handles the request on that end?
Do queries and commands continue to be considered separate here?
Yes, typically you would fire a command and if you need to update the UI after this action has been performed you would perform a query to get the new information. An example will make this clear.
Let's say you would assign a specific guard to a certain area. The only information the command (which is only a DTO) needs is the Id of the guard and the Id of the area. The associated CommandHandler will perform all tasks to handle this, e.g. removing that guard from another area, booking him as unavailable etc.
Now your UI would want to show the change. The UI has probably some kind of list with all guards and their assigned area. This list will be populated by a single GetActiveGuardsAndAreaQuery which will return a List<GuardWithAreaInformationDto>. This DTO could contain all kinds of information about all guards. Returning this information from the command is not a clean separation of concerns, because the atomic command handling could be very well used from a similar but slightly different UI, which will require a slightly different update of the UI information.
such as a login attempt. Is that a query or a command?
IMO a login attempt is neither. It is a cross cutting concern, an implementation detail that the data is hidden behind a secure connection. The application however should not be concerned with this detail. Consider using the application with another customer where you could host the WebApi service in and Active Directory domain where you can use Windows Authentication. In that case the user only has to login to his machine and the security is handled by the client and server OS while communicating.
With the patterns you're referring to this can be nicely done using a AuthenticateToWebApiServiceCommandHandlerDecorator which makes sure their are login credentials to serve to the service by asking the user in a modal form, reading it from a config file, or whatever.
Checking if the credentials worked can be done by performing a kind of a standard Query your application always needs such as CheckIfUpdateIsAvailableQuery. If the query succeeds the login attempt succeeded otherwise it failed.
if a command handler returns void, how would you tell the presenter whether or not the user creation request was successful?
While it seems that void doesn't return anything this is not really true. Because if it doesn't fail with some exception (with a clear message what went wrong!) it must have succeeded.
In a follow up of the mentioned blog posts #dotnetjunkie describes a way to return information from commands but make notice of the added comment on the top of post.
To summarize, throw clear exceptions from failed commands. You can add an extra layer of abstraction client side to handle this nicely. Instead of injecting a commandhandler directly into the different presenters you can inject an IPromptableCommandHandler which has only one open generic implementation at compile time:
public interface IPromptableCommandHandler<TCommand>
{
void Handle(TCommand command, Action succesAction);
}
public class PromptableCommandHandler<TCommand> : IPromptableCommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> commandHandler;
public PromptableCommandHandler(ICommandHandler<TCommand> commandHandler)
{
this.commandHandler = commandHandler;
}
public void Handle(TCommand command, Action succesAction)
{
try
{
this.commandHandler.Handle(command);
succesAction.Invoke();
}
catch (Exception)
{
MessageBox.Show("An error occured, please try again.");
// possible other actions like logging
}
}
}
// use as:
public void SetGuardActive(Guid guardId)
{
this.promptableCommandHandler.Handle(new SetGuardActiveCommand(guardId),() =>
this.RefreshGuardsList());
}
At the end of the day, for any given UI task (say the user creation request), does it end up that you end up having a winforms client based query/command, as well as a web api service version of the command/query which handles the request on that end?
No!
Client side you should create a single open generic CommandHandlerProxy which solely task is to pass the command dto to the WebApi service.
For the service side architecture you should read another follow up: Writing Highly Maintainable WCF Services which describes an server side architecture to handle this very nicely. The linked project also contains an implementation for WebApi!
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
I don't understand some code in the Microsoft.Web.WebPages.OAuth namespace, specifically the OAuthWebSecurity class.
It's this method here:
internal static void RequestAuthenticationCore(HttpContextBase context,
string provider, string returnUrl)
{
IAuthenticationClient client = GetOAuthClient(provider);
var securityManager = new OpenAuthSecurityManager(context,
client, OAuthDataProvider);
securityManager.RequestAuthentication(returnUrl);
}
The first line is fine => grab the provider data, for this authentication request. Let's pretend this is a TwitterClient(..).
Now, we need to create a SecurityManager class .. which accepts three args. What is that 3rd arg? An OAuthDataProvider? That's defined as a static, here:
internal static IOpenAuthDataProvider OAuthDataProvider =
new WebPagesOAuthDataProvider();
And this creates a WebPagesOAuthDataProvider. This is my problem. What is this? And why does it have to be tightly coupled to an ExtendedMembershipProvider? What is an ExtendedMembershipProvider? Why is this needed?
In my web application I'm trying to use a RavenDb database and my own custom principal and custom identity. Nothing to do with Membership or SimpleMembership that comes with ASP.NET.
What is that class and why is it used, etc? What's it's purpose? Is this something that DNOA requires? and why?
I didn't write the code you mention, so I could be wrong here, but I believe the ASP.NET code you refer to is indeed bound to their Membership provider.
If you aren't using the ASP.NET membership provider, I would suggest you simply use DotNetOpenAuth directly (as opposed to through the facade that Microsoft added), which has no such tight coupling.
If you don't need the ASP.NET Membership system to provide local login accounts (accounts stored in your local membership database) on your system I wouldn't go down the Route of using any WebMatrix based bits (WebSecurity / OAuthWebSecurity).
They actually make it harder to interact with DNOA and more or less hide all the interesting bits at the same time anyway ...
As I needed local acounts I ended up pulling all the source code for this into my source code and then editing it from there (I had other reasons for doing this as well, not just to enrich the interaction with DNOA).
If you need local accounts - use WebMatrix
If you don't need local accounts - use DNOA directly.
I am creating a graphical tool in silverlight which reads data from multiple files and database.
i dont want to call the database again and again. i want to retrieve the data when required and keep it safe somewhere so if the user or any other user visits the same page, they can then access the data.
i want to use application state of asp.net Cache["Object"] but in Silverlight? what is the best methodolgy?
Since silverlight is running client side you need to cache serverside.
You could fetch your data with WCF.
Something along these lines:
What I have done in the past is to cache the query using a WCF using enterprise library:
public class YourWcfService
{
ICacheManager _cacheManager = null;
public YourWcfService()
{
_cacheManager = EnterpriseLibraryContainer.Current.GetInstance<ICacheManager>("Cache Manager");
}
}
your web method would look something like:
[OperationContract]
public List<Guid> SomeWebMethod()
{
if (_cacheManager.Contains("rgal")) // data in cache?
result = (List<Guid>)_cacheManager.GetData("rgal");
if (result == null)
{
result = FETCH FROM DATABASE HERE;
// cache for 120 minutes
_cacheManager.Add("rgal", result, CacheItemPriority.Normal, null, new AbsoluteTime(TimeSpan.FromMinutes(120)));
}
return result;
}
Silverlight controls run in browser/client side per user, so caching something for all users on the server is not possible.
You can cache data in the control for given user's session or in isolated storage for given user. But you can't do anything on the server without writing corresponding server side code.
Is the caching really necessary? Are you really pounding your database that bad?
Your DB is your storage. Unless you have a performance issue, this is premature optimization.
The new Enterprise Library Silverlight Integration Pack provides you with capabilities of caching on the client. 2 types of data caching are supported: in-memory and to isolated storage. You'll also get flexibility of configuration of the expiration policies (programmatically or via external config) and a config tool support.
Note: it's a code preview now, but should be releasing as final in May.
My applciation works as follows
[user]----username/password/domain----->[WCF service]
then i access the domain server to see to which actual DB the user is associated,
after getting that, i validate the user in his actual DB(DB is per domain)
the problem is that i need a place to store the domain name for the following requests against the db.
for example,if the users calls a WCF service operation:
Test()
first the validation procedure is called, (WCF UserNamePasswordValidator) which validates the user password(which is sent as part of the header for REST or as part of the SOAP), and the next function to be called is the Test, but by then i cant tell the domain of the user(to actually serve the request agains that domain..)
I dont want to change the signature of each domain to
Test(string domain)
I cant simply access the headers since i expose the same methods both as REST and as SOAP and the authentication is different for each of them..(one is with headers as with Amazon S3 and the later is using the SOAP standard)
so basically i'm looking for a global, per call storage.(i want to avoid the Per-Call initiation method)
thanks.
EDIT:
Maybe i should use the ThreadStaticAttribute? will that work?
This will not work. You can't store anything in UserNamePasswordValidator. It even doesn't have access to OperationContext because it runs on different thread.
The way to do this is create custom message inspector and extract the information from custom message header to custom operation context extension as Frank mentioned.
WCF knows a Current OperationContext. You can write your own extensions for it. Unrelated to this issue, I used the same mechanics in this NHibernate Session management here, which may work in its concept for you as well. It accesses the InstanceContext, but the concepts are similar.