Hi Developers/Architects,
This is more of an Architectural question:
I have a web application. The application use ASP Membership API (froms authentication) for users/roles management.
We host a separate application for each of our clients. So basically each client has an Application Name in ASP Membership database. That client then create his roles/users according to his need.
The reason why we have same website, hosted on IIS for each client separately under client name's virtual directory, is because all of the clients have their separate Application Name (in terms of ASP Membership), and the underlying database is separate for each client as well.
so each client has a separate URL, e.g: http://mysite/client1. and then client1 has his own users, roles. The underlying application database used by application is clients individual.
The Web Application and the database schema is exactly same for all clients.
I can not take any decision regarding the database part. So i am not going to discuss that.
But i want to change the approach of hosting separate application for each client. I want to host one application for all clients:
this brings some questions:
Q1. how would i create these urls: http://mysite/client1, http://mysite/client2 (as i can not put names of all clients on the main login page, and then once user selects the client name, provides username/password .... i can not do that due to the nature of the business)*
Q2. I can not create single application (on IIS and on ASP Membership level) and then separate clients by roles, because all clients have roles within themselves, and plus, 2 or more clients can have a user by same name; so userX for client1 and userX for client2. theses users are different, but they happen to have same names.
* One solution to Q1 can be: that i create a new forwarder application, which is hosted for each client separately in IIS under client's virtual directory. And when client opens their url (e.g: http://mysiteforworder/client1) they are redirected to (http://mysite/Default.apsx?app=hjuk98jkio8) where (hjuk98jkio8) is a encrypted name of the client, that we use internally.
this would resolve Q1, but not Q2.
let me know what options do I have ...
Here's an idea I've used a few times before.
You can set up multiple Web Applications / Virtual Directories in IIS, e.g. /client1 and /client2, that point to the same physical web application path on disk. That way the code is still the same for all customers, all managed centrally, but there are different URLs for different customers.
Using WMI you can even script or automate creation/maintenance of the webapps/vdirs in IIS.
To determine which DB to connect to, or which app is running, you can look at the URL being accessed and use the first part of the path as a key into a configuration dictionary for that customer.
Related
I have a scheduled task to create to get data from a site using the webclient
class. How do I execute a database update with the data retrieved under a different windows user? I was told not to use the same account to access the site as performs the update. Should I just create a windows service that runs the web request then call a db component with authentication settings set under IIS to run under a different user? Or is there a tidier way to do this running a single exe as a scheduled task? The Scheduled task runs under a single user. Could I run the task and switch user for the update? We are using Windows authentication at the database level.
Run two Windows Services. One to get the data from the website, running under Account "A" which stores the data locally. The other Windows Service running under Account "B" picks up the locally stored data and executes the database update.
Other designs will require you to store the credentials somewhere in a config or other file - this way the Windows Services are always running under the correct account for the task they are attempting.
You clearly stated that you will have to use a Windows user to get access to the database. However, often this will not be the case when you authenticate against a web site so exactly how you solve your problem will depend on the details of that.
You should probably execute your process as the Windows user that has access to the database. Then you have to solve how to authenticate against the web site. If the site uses forms based authentication it is a bit complicated but there is an answer to the question WebClient accessing page with credentials that might help.
If you need to use the WebClient.Credentials property to authenticate against the web site you might find it easier to execute your process as the user that has access to the web site. You then need to use impersonation to access the database. A simple way to do that is to use the SimpleImpersonation NuGet package.
In most cases you will have to store the password for one of the users so your process can use it to either log in to the web site or impersonate the user. A relatively safe way to store the password is to use the Windows Data Protection API (DPAPI). The class ProtectedData can assist you in storing secrets so only a specific user on the computer can access the secret (e.g. the password).
We have a multi-tenant Asp.Net MVC 4 web application with each tenant having its own repository of files (a folder in the file-system). We took the shared database, shared schema approach and we identify tenants by their subdomain.
What is the best way to ensure that a tenant can only access his repository folder and no other folder in the file-system? we check it in the application business logic, but what if we make a mistake...?
When running the application, all tenants run under the same user (which is defined in IIS application pool).
Do we need to serve each tenant as a separate user - using impersonation? do we need to impersonate each time a request is made to the server - in order to fill it?
I've heard this has performance drawbacks and is not the prefered way, but what is?
We also have a windows service which fills requests in the background (for all tenants), sent to it through MSMQ. Does this service also needs to change its identity every time it gets a request?
Edit:
In addition, we need a type of isolation which if someone uploads a file infected with a virus - it will affect only this tenant's files, and not every tenant on the server. We use ant-virus software, but we need this separation also in case the antivirus software will not identify the virus.
Thank you
all tenants run under the same user
If each tenant has a separate IIS Web App and identity (whether app pool or "normal" user), then you can use NTFS access control.
These does not depend on having all users having a local or domain user accounts on the web servers to allow impersonation (and this NTFS access control).
However it will add memory overhead on the servers of course – each tenant will have their own worker process.
[…]MSMQ. Does this service also needs to change its identity every time it gets a request?
I'm not sure you can do impersonation based on MSMQ messages, I would expect this not to work (MSMQ messages do not carry the necessary identity information).
Anything shared is going to need to be implemented to check all access: depending on the nature of the processing this may be more difficult (eg. if client requests can be something of the order "get information from the file" for an arbitrary file: the service would need to do the access checks1).
1 There are Win32 functions that will do the heavy lifting.
For the past 2 years we have created 3 desktop application and 2 admin section(web) for one of my client.
Every application uses its own authentication process.
I have merged the authentication process for web in single unit.
But the client wants to have one screen for getting authenticated on desktop application as well as on website.
he also want to use different browser and the username /password should be asked only once irrespective of browser opend.
I tried to use cookies for web. but every browser has got its own cookies.
Can any one suggest how can i authenticate a user for the whole computer so that authentication information is available to desktop application as well as to website irrespective of the browser being used?
Edit: As suggested by joe using windows authentication is not possible in my case.
So i created one more table with following column
ip,userid,authenticatedat
when ever a user is authenticated i insert its ip,userid, and time in table.
when ever a non authenticate user comes first i look in the table if the ip is present and authenticatedat is within 30 min i assume user is authenticated and set the session/variable with data required.
This i have checked and found it is working .
I have found this is not secure.
Windows authentication is the only way I know of doing this. Assuming your users are on a domain you control, then their Windows credentials would validate them, and they wouldn't ever need to enter a username and password.
Outside of that, I can only think of hacky dirty methods of making this happen. You could install a single authentication service on their machine which is available to connect to remotely from other applications - those apps would call your service, and that service would authenticate the user and pass an authentication token back. Easy enough for Windows apps, but making that work on a web app wouldn't be fun. Your web server wouldn't be able to talk to this service, so you'd have to rely on the client javascript talking to the service and retrieving a token or hash, and then the javascript passing this on to the web server.
Anything you put on a local machine, you have to assume the user can reverse engineer and manipulate, so if you need real security, I doubt you'll find a solution. Best bet is just to make the user log in every time you need to, and have your authentication/authorization code on your web service layer.
I'm creating a WCF service to share all membership operations (such as user creation, login, change password, etc) between multiple applications (websites, WS, IPhone App, etc), using the ASP.NET Membership Provider.
I want also to store information about application sending the request.
I'm wondering if it make sense to dynamically set the Membershio provider's Application
Name so to store this info in the membership tables? Since the provider is a singleton it would be something like :
System.Web.Security.Membership.ApplicationName = application;
bool isValid = System.Web.Security.Membership.ValidateUser(username, password);
It actually works but don't know if this is a proper use and if it can cause any trouble in future. Usually as far as I know the application name comes from the Web.config (but in my scenario it would be always the same, the WCF one) and I haven't seen any example where this Property is dynamically set.
Another option would be to store this info in a separate table and leave the Application Name static coming from web.config.
Any suggestion is welcome!
That's not what the application name is for in the membership providers.
You say that you want the user accounts to be shared between multiple applications. In this case the membership application name must be the same between all applications.
The app name is there to allow multiple applications to share the same database but keep their users isolated - a web site configured with an application of app1 will not share users with an application of app2 even if they share the same physical membership database.
Log it elsewhere!
How can I create a subdomain in an asp.net C# application? I am working with an asp.net portal. In that portal I need to be able to create the subdomain at runtime. The ftp for that subdomain also needs to be the same as the main domain ftp.
There are a handful of working parts here. It sounds like the requirement is that this all happen at runtime. I am sure a lot of web hosting providers are deep into these sets of problems and likely have custom solutions.
DNS: you'll need to have an API open at the DNS host. If it's a LAN environment, you'll have to check your DNS provider on whether they have APIs exposed. (i.e. Windows Server or whatever your network operating system is). If this is a public facing site that needs to be accessed via the internet, you'll have to get those APIs from the DNS registrar. Are the subdomains to be permanent?
IIS: You'll have to setup wildcard mapping, (i.e. *.mydomain.net). When an HTTP request comes in, logic within the ASP.NET page can determine the subdomain that you're working with. You could extract the subdomain, perform a lookup on that subdomain to get more information (CustomerID, names, valid visitor IP address ranges, whathaveyou).
FTP: if you require secure logins for that subdomain, you'd have to have created AD or local machine accounts for those users. If you want anonymous access, that's OK too. There are some scripting options that you'll have to look at to have that FTP folder setup as well. That is assuming you're using IIS's FTP module. If you are using a 3rd party FTP application, that complicates the scenario even further. Their APIs would have to be investigated.
Active Directory: If you are requiring secure access for each subdomain, you'll have to create AD users and/or groups. You can certainly script the creation of users into groups. Perhaps the users will be local to your web server. That doesn't scale well if you want to add another web server, but it's certainly do-able.
subdomain's are controlled by your dns settings. Beyond that I can't understand your question.
I think the best way is to have a wildcard DNS entry - i.e. *.domain.com that points to the domain. And then use a rewriting tool, like helicontech.com, to rewrite the 1st part of the subdomain to tell your app what you're looking at.
This would use regular expressions to pass the subdomain to your app:
RewriteCond Host: (mysub).domain.com
RewriteRule (.*) /$2?subdomain=$1 [I,L,U]
There are two halves to this:
A) Changing your DNS Settings:
This varies based on your host and whatnot. Contact them and ask if you can't figure it out.
B) Changing your host settings:
This varies based on your server. I assume you're using some version of IIS.
In IIS6, you can right click a web site, select the properties page, go to the web site tab, select advanced in web site identification, and start adding bindings (Generally you'll use default or the ip address for IP Address, 80 for TCP Port (unless SSL), and the site for the host header file (e.g. www.example.com or subdomain.example.com).
In IIS7, you right click on a website and select edit bindings, then click "Add". IIS7's add screen is pretty self explanatory.
I think he wants to created a subdomain from code, using an API probably that needs to be provided by his webhost folks. Like his own DNS manager app. If I interpreted your question wrong, then I guess you probably oughta reiterate a bit more.