Shared Application - c#

I am creating an application to be accessed by multiple clients, but
each customer will have a different database, only access the
same application in IIS, I'm using DDD, C # and MvC3 and Entity Framework 4.1 CF. Does anyone have any example or an idea of how best to configure the connection string
specific to each client?

First, you need to identify whether it's a database per client (machine?), user identity authenticating, or some other identifier. For example, if it's per account, then two machines may be able to authenticate as that account and get the same storage.
Once you have that identifier, you'll need a master table somewhere with a map of account to database connection string. You'll probably also want to cache that table in memory to avoid two db roundtrips on every request.
That global configuration information is typically stored in a database. You could go as simple as a file but that would cause problems if you ever wanted to scale out your front end servers, so common storage is best.

Related

best practice for DAL and configuration on Multi-Tenant isolated DB

My company holds a dozen websites and isolated DBs (identical schemas).
every customer has its own website (different app pool) and DB.
every website has its own configuration, several connection strings, but they all have same schema for configuration.
cust1.domain.com
cust2.domain.com
cust3.domain.com
We would like to merge all websites to one (single app pool) and stay with isolated DBs for security and large amount of data reasons.
what is the best practice for designing a DAL and configuration of it?
what are the implications of it, if large amount of tenant will be on the same time? does one application pool can manage this situation or it can be managed somehow?
BTW, we are using asp-membership for users authentication.
Thanks in advance,
Eddie
Use Application_PostAuthenticate event in global.asax to load the correct database and then close the connection in Application_EndRequest
One option is to use the profile in membership and store a piece of information that will allow you to determine which of the actual db's they should be connecting to. Downside is that you will need to store this piece of information for the duration of the users session so either a cookie or session variable is likley to be needed.
The implications of one site vs many depends a lot on your environment and application, do you currently have the multiple sites on a single box or do you have a web farm? do you know the number of concurrent users for each site, the amount of traffic? Performance monitor can help you here to see how busy each site is but you may need more invasive logging to determine metrics such as concurrent users. I found this server fault question around IIS 7 performance which may be of help
You can try 'Shared DataBase With Different Schema' from multi tenant data architecture . In your DAL you can choose specific schema which perticular to current user. Simple and secure in this way
Continue reading http://msdn.microsoft.com/en-us/library/aa479086.aspx

Asp.net MVC4 Storing sensitive user data

I have a Asp.Net MVC4 website which can connect to multiple databases depending on the user's login credentials. In order to get the database access list for the user, I have to perform a few complex joins when they login. To avoid having to do this more than once, I am currently encrypting and storing the database ID in a cookie. I now realize that this may not be a good idea and even strong encryption may be broken. In addition, the encrypted cookie is transferred around on every request increasing traffic. I am now thinking about using the HttpContext.Current.Cache to store the data instead. Can anyone comment on whether this is a good idea. I would also be interested in knowing if there are better options out there. My website is not deployed on a server farm right now but what would be the implications if I were to use a cache and a server farm in future?
Based on your requirements (i.e. keep a hold of sensitive user specific info across a session), the correct place is for this is the SessionState. AFAIK sessions states can be shared across multiple web servers so if you did use a server farm you wouldn't need to change anything.
Session is right container for user sensitive data. Or you can store it in database and get it there by some identifier that is stored in session(it is useful if you store large amount of data).

How do you secure your sql servers accessed by C# applications

Simple and contrived example:
C# desktop application talks to SQL Server database. All orders exist in Orders table.
Application views, creates and amends orders. In this example a user can only amend their own orders.
Concerns:
Storage of connection string if using dedicated sql credentials.
Even if user credentials are used, application security could be bypassed by connecting directly through Excel or Access.
Solutions:
Provide access to SQL through web service/middleware only. Good, but not necessarily viable in this case.
Encrypt connection string in application somewhere. Not hugely secure, security through obscurity.
Secure database by granting access to specific stored procedures, views, etc and no access to actual tables. SP's and views take into account the user's rights/credentials. Pretty awful. Ok for simple examples (Select where user , becomes complicated once you introduce users in different groups, manager relationships, etc.
Alternatives:
How would you approach this?
Thanks
Even if user credentials are used, application security could be
bypassed by connecting directly through Excel or Access
what do you mean? you should not allow users to connect to SQL Server directly or with Excel or Access. They should NOT know the sa or other password.
After this, surely you could encrypt some sections of your app,config so that nobody can see its content.
I would really have the logic that a user can only modify his/her own Orders at the application level. Could be done also in the stored procedures I guess but it depends and more details should be known about this to suggest the best or most appropriate approach.
Use windows authentication instead of sql authentication.
To allow users to see only their data you can create view and filter data based on the currently logged in user by using SYSTEM_USER to get the data for the current user only and deny select permission on the table itself.
You can't do row level security in SQL Server (well you can, but it's not straightforward). So your only choice to be totally secure is to go through a data-layer which controls access. You can store your credentials encrypted, but that's not totally secure, as you say. It depends what you need.
Well in our application we handle we store the connection string encrypted in a file.
So the user has no direct access to this file.
We also use sql connection only to our database and grant the user for this only.
If you use Windows Credentials to access it and want to prevent any manipulation you can disallow write access to table.
For reading the data you can build queries or access the tables.
For writing/adding/manipulating data you can create stored procedures. One of the parameter is the username. Inside the procedure you build your bussiness logic, impersonate to a user that has write access to finally write/update the data.
There you have your "layer" inside the SQL server.
But I wouldnt suggest to go this way :) It is possible but to many business logic inside the database imho. So the safest way is to find a good encryption class in your language, use sql auth only and store those data inside your code.

Saas with database per client - single point for entry for services. Performance overhead?

I'm building SaaS application where back end will be SQL Server and WCF Services.
Here is where I'm little worrying.. I'm planning to have separate database per customer (thats decided) and will authenticate users against their database. Thats decided as well.
There will be central database which will have customers info like what database is their and what endpoints to use.
Ideally, I want something like this:
a. Client hits main page ASP.NET or
Silverlight or open client app on
PC/mobile device/etc
b. Types in Customer ID, user name
and password
c. Call being made to main URL
d. I will pull endpoint and DB
information for this Customer ID. I
do want WCF endpoint info also be
configurable for future
expansions/upgrades
e. Need somehow pass information
about endpoint/database to user.
Multiple customers can share same WCF
endpoint.
f. Call endpoint from client and
login to specific database.
This way I can see how performance will be OK since I won't have to go through my "system" proxy on each call. Client will KNOW what endpoint and which database it deals with.
But I'm not sure how to implement this securely. Because database information in step "e" will flow back to customer. Technically, even if it's cracked on customer - still no access to DB itself from outside. But not nice..
What your thoughts are? Or should each call be made with companyID token and then main central service will route those calls? But that's like single point of failure. I'd rather see main server to work on on login.
We've done WCF sites connecting to multiple databases handling 1000 concurrent requests, there are fiddly bits in the WCF config that you need to tweak, but it should work fine.
I don't see why database information needs to 'flow' back to the user.
All of that could happily live server side. Then all decisions about what database to connect to can be made based on the user credentials.
If you want multiple endpoints to handle load, then you redirect to a relevant (or random) end-point after login. Then store the relevant routing/mapping data on the relevant endpoint (or all of them if you're using random).
All you need from them is their credentials to decide what database to use.
Tip: As with all performance issues: measure, measure, measure. You need to know if there is any benefit with multiple end-points under your expected load; so build a load test. Then you can see where the performance hit is. Over engineering before measuring sometimes works, but always wastes time.

WCF -> ILM -> Web Services -> SQL Server

My employer currently has most of its access to the database through C# sqlDataAdapters and sqlCommands on a WebServices server or components in applications. These are mostly Windows Forms apps that are ran on intranet and internet depending on their functionality.
I have been researching WCF quite a bit and I feel it would be a good fit for our us. Also my manager has a copy of ILM(MS Identity Lifecycle Management Server) that he would like to use to to provide SSO support for authentication and authorization for all of our applications.
Our applications request data from the database and it is returned in dataTables primarily. I know collections are better, it is just the established practice used. So I am trying to find a solution that will be secure, authenticate through ILM and return data to the client in a dataset(at first, migrate to collections later) from webServices server.
My question is will this work or will it be too slow?
Client calls routine on WCF requesting data
WCF server checks with ILM to see if its ok to do so
WCF calls webServices server to get the data
Dataset or collection is passed back to the client.
If this is feasible how would I go about connecting to ILM for authentication. Is there a slick way to do it in the Web.Config file or would I have to do it on the message level on my own?
Thanks in advance.
I am familiar with ILM. It's not an authentication service. ILM means Identity Lifecule Manager and it's a pretty good description of what it can do. It can provision new users, deprovision old users and allows you to copy identity data between identity stores. It also provides a password synchronisation service. You still use Active Directory or AD LDS (ex-ADAM) or some other directory for AuthN and AuthZ.
Whilst ILM stores a whole load of data about your users, you are strongly discouraged from accessing that data directly.
[EDIT]
ILM does not provide LDAP services. Think of it as a manager: it doesn't do any work itself, it just rearranages things periodically. As your manager moves round data in the form of emails, it moves round data in the form of account details.
ILM is a tool for managing identities across directories and databases. It doesn't make sense to consider ILM in the context of a single store, SQL, AD or any other - its job is to marshall data between stores. It wouldn't have anything to do if there was only a single store.
Here's a typical scenario: you create a SQL table called People containing columns for firstName, lastName, jobTitle, department, a uniqueID, startDate and endDate. ILM is hooked into this table. It does a daily import and there is a new row. ILM uses the data in this row to create a userID in AD, another in Domino and another in a different SQL Database. It uses the jobTitle and department fields to assign group membership in AD, mailing lists in Domino and permissions in SQL.
The user starts and works for a few weeks and then resigns. You set the endDate in the table and ILM notices this change on its next import. It updates the AD account to expire on that date and stores a delayed action to delete it after 90 days. 90 days later, it deletes the account. Likewise with the other accounts.
You can use your personnel system instead of the SQL table but (a) it's not usually in the right format or maintained timely enough and (b) they're often itchy about letting you have access to their data.
I'm not hugely familiar with ILM, but I'm guessing that it is pretty granular to specific data queries. With WCF you can hook your own identity-provider by implementing IAuthorizationPolicy (like so) and providing your own "principal". I suspect it would be pretty easy to write a principal that works against ILM, but this would presumably be for pretty broad checks - "do I have CustomerAudit access", rather than "can I access CustomerAudit for customers in the north-east".
A nice thing about using a principal is that you can also use [PrincipalPermission] checks on methods, so you don't need to add broad security checks to your code (the CLR enforces [PrincipalPermission] directly).

Categories