I'm creating a new middle tier where all of our client calls will go through a WCF service. We're using ASP.NET membership with the service in order to authenticate users. The middle tier will be hitting an existing database in which we already have an InetUsers table containing usernames and passwords.
This is where it starts to get messy. This new middle tier will be used by our web application, but not by our existing desktop application, which will - until we rewrite it at some point in the future - be using the old COM+ middle tier. Administration of the users for the web application takes place in the desktop application. In other words, users will be created and passwords set and changed from within the desktop application, which in turn hits the already existing InetUsers table.
Ideally, what will happen is when we deploy the new middle tier, we'll take all of the users from the InetUsers table and create records for them in aspnet_Users and aspnet_Membership. Then we'll set a trigger on the InetUsers table to keep aspnet_Users and aspnet_Membership up-to-date.
There's a whole bunch of questions wrapped up in this, so I'll try and list them all out here:
Is this the right approach? Obviously having this data in two places isn't ideal, but bear in mind here that I'm not the final decision maker here and we're kinda stuck with some legacy stuff here, at least for now. Still - maybe there's a better way.
In the same vein - would we be better off coding our own membership provider rather than using the SqlMembershipProvider? How difficult/easy is it to do so?
If we use this approach, I plan on using the aspnet_Membership_XXXX stored procedures for the initial population of the tables as well as in the triggers. Having done some research into this, it appears that if I want to call aspnet_Membership_CreateUser directly from SQL (ie in a trigger...) rather than using the API, I have to store clear text passwords since I can't get the salt and the hash right otherwise. Is this true?
Does any of this even make sense or am I going about this the wrong way to begin with?
Much appreciation for any help offered.
If you already have a database structure, I would write a custom membership provider and skip the existing membership structure. That way you are using one database structure that the developers are already used to, whether for data access, reporting, or other purposes. Create a class that inherits from MembershipProvider. Check this out: http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx or http://www.devx.com/asp/Article/29256/0/page/3.
You only need to implement the features you actually need.
It isn't "difficult" to code your own membership provider. If you're planning on living with the hybrid solution for a while, it would probably be cleaner to roll your own provider than maintain the data in two places.
Then, when you're ready to move to the new, standard, membership provider, it should just be a matter of transfering the users over once and re-pointing to the new provider for both the desktop and web interfaces.
Related
I am testing out Identity for my ASP NET CORE MVC application. From what I have read the Identity solution provided is probably the way to go now considering user management and security for logins.
What I have not yet understood is if it is somehow possible to combine the Identity solution with custom groups?
Let me explain..
Lets say I create a webpage for Factories.
This means that several customers that own these Companies that run the factories would like to use this system.
Company A has 3 Factories with 100 workers on each factory.
Company B only has one factory with 20 workers on that factory.
I have read alot of roles and that of sort on how we could seperate these by roles. What they can see, what they can do. But how in the world do I isolate Company A from Company B?
The old fashioned SQL table way would be like to have a Users table, a factory table and a perhaps Customers table. And from there build the logic. But with Identity it does not seem to work in that way?
Any suggestions or links to further reading about this would be appriciated! And even if you guys know that Identity is not the way to go for this kind of solution, then be it. Just so I don't waste any time on something that perhaps is not meant to be.
There's a lot to unravel in your question, but I'll give it a shot. At a high-level it sounds like you're looking for a multi-tenant system.
and pretty much everything you're saying is on point, you probably just need an example to get going. If so, check out Microsoft's example of a multi-tenant system. It might be enough to get you going.
There's several different approaches to a multi-tenant system depending on your business requirements, but here's a few of the more common approaches I've seen used:
Database Isolation - Each Company would be in a separate database. When a user from Company A connected, you would be able to look up which database/schema you should connect too.
Row Level - All companies store data in the same tables, but there's a column called something like "company_id". Every time you query against the table, you filter on company_id based on which user is logged in.
Instance per tenant (AKA Standalone) - On this approach you essentially have multiple web servers running, one per company. They are completely isolated from the web server all the way down to the database. This can be desirable in some situations, but requires a bit more hardware. On the code side, you can handle this fairly effectively with just moving relevant settings into the appsettings file.
Further Reading:
Identity Management In Multitenant Applications
Multi-Tenant Patterns on SQL Databases
Row Level Multi-Tenant Example
The implementation for the different companies changes depending on how you decide to implement the multi-tenant system. So it's hard for me to give you any concrete advice on implementation.
The only word of warning I'd give is think through the relationship between a user and a company. That could change/complicate your implementation fairly quickly.
Can a user be part of Company A and Company B at the same time?
Hope this helps a bit, and best of luck.
I have a C# project called Authentication that allows users to login and get their login credential checked and if passes, returns the token.
I want to reuse that C# Authentication project for other Applications that I am designing. Is it a good practice to store all the users from different Applications in one table or is there a better way to go about coding for One Authentication project for many Applications?
It depends.
There is a difference between code reuse and infrastructure reuse. The former is OK as you get a clean separation between the applications. Sharing a database is not recommended as it can introduce security vulnerabilities if you do not design it carefully.
I would also separate the notion of users and accounts. An account is used to log into an application and load the correct permissions. i.e. the account controls what an user can do in an application while the "user" object describes the user itself.
If you separate it like that, it's much easier to create a reusable library as everything related to authentication/authorization is in its own part. That's because the authentication design rarely changes. What differs in applications is typically the information that describes the user and the kind of customization that every user want to have.
Short answer:
Separate everything related to authentication and authorization into an "Account" object.
Collect everything describing the user into an "User" object.
Reuse the account part, but build the "user" part in every application.
Never, ever share the database between services. It will create a maintenance nightmare.
Every DB should be designed around (and after) the Bounded Context handled by the relative microservice.
In your case this means one DB to store the authentication data, then another DB per-service, with the relative data.
It is perfectly fine to have a Users table in separate DBs holding some duplicate data. As long as you're diligent enough and have a good strategy for keeping that data in sync.
I’ve created a custom MembershipProvider that uses the DotNetNuke.Security.Membership.MembershipProvider as a base. In our implementation, a CRM system stores all contact data for users able to connect to any of our websites, and therefore such functionality as CreateUser and DeleteUser are not implemented. The MembershpProvider only handles authentication, membership and returning a UserInfo object with the CRM system’s data.
This works fine.
The problem I’m running into is with the PersonalizationController. Our CRM system stores information regarding the user/contact, but not regarding the user’s personalization settings. I would like for DNN to continue to store the personalization settings as defined in the PersonalizationController / PersonalizationModule (e.g., in the Profile table). The problem is, when the LoadProfile() stored procedure is called by the DataProvider it fails on an update because the Profile table has a constraint associated with it requiring the UserId to have already been added to the User table. I could modify this Foreign Key relationship but that wouldn’t be good architecture.
So, the question is: What would be a good architecture choice in this situation?
The MembershipProvider and DataProvider follow the Provider Model, so they can be replaced, but I don’t want to replace the DataProvider. The PersonalizationController doesn’t follow the Provider Model and therefore cannot be so easily replaced. Updating the Stored Procedure or the Foreign Key would potentially cause upgrade issues (or at least make debugging years later hard / require good documentation). Likewise with changing the source code (I could simply update the PersonalizationController, line DataProvider.Instance().AddProfile(userId, portalId); with a call to first add the user to the Users table (which should be unnecessary – yes, I understand the difference between the Users and aspnet_Users tables, so theoretically, adding a User record should be OK, albeit superfluous simply because of a Foreign Key. I could also update the MembershipProvider with an insert into the Users table -- this is the direction I'm currently thinking about (although I don't really want to).
Any ideas how I can replace the PersonalizationController using a Provider Model? Or how else I can minimize upgrade or management issues down the line? I’m really trying to build a system where we can at any time install DNN fresh and simply install all our Modules / Providers / Skins on it and replicate the existing system (without content, of course).
What would be the recommended way / recommended architecture in this situation?
Thanks in advance.
Greg
Would it make sense to keep the UserID in the DNN database, so that you can utilize all of those keys that many different modules may have on the Users table. If you don't have userids, it is very likely that you will run into module issues down the line.
The AD provider for DNN creates DNN users, and matches those up to AD users, to get around this issue.
I have been struggling with this for some time, and can't seem to find any info.
I have created an online point of sales system using an SQL database, EntityFramework, ASP and .Net4 in C#. My previous programming experience has been with OpenGL and DirectX, so this is all very new to me.
Users from a single company will log into the site using a single account. They can then use the online till and backoffice. Thus far the software has been developed using a single SQL database. What I would like to do is have the application create and use a different instance of the SQL database per account.
Does this sound sensible/possible, or would you expect to have a single huge database for all users? - Note: there could potentially be a huge number of users which each store a lot of information and each user will only need access to their own database.
Any suggestions would be greatly appreciated
Thanks,
I think this is not a good approach, as if there will be any scheme changes in you will have to keep synchronize each database instance.
Does this sound sensible/possible, or would you expect to have a
single huge database for all users? - Note: there could potentially be
a huge number of users which each store a lot of information and each
user will only need access to their own database.
This is possible, but it is not at all sensible. Users don't access databases, applications do. Separating a full database per user only makes sense if your application is offering users the capability of creating their own data structures within the application (such as a hosting provider would do). If it is simply meant to house multiple identical structures keyed off each user, then you'll be better off spending your time normalizing a proper relational structure (an assumption since you mentioned you're using SQL) and optimizing queries/stored procedures to make data retrieval/insertion fast.
RDBMS is perfectly capable of handling huge amounts of users and large subsets of data if you normalize it effectively keying each structure appropriately (in most cases by the userkey).
The best approach is to have a single huge database for all users.
SQL Server will only support 32,767 databases per instance.
http://msdn.microsoft.com/en-us/library/ms143432.aspx
Good afternoon - I have a pretty general question today - I've been tasked with creating a web application to manage some basic information on customers. It's a very simple application, but what I don't know is what to keep in mind to develop the site around supporting multiple users at their own domains or subdomains of our url?
How would I restrict users from logging in to each others portion of the app?
I've seen mention of database scoping in similar questions on Stack Overflow, could anybody elaborate on best practices for an implementation like this?
Are there any new features in MVC3 to support multi-tenancy? I am facing this issue with MVC2 and my eCommerce site where we decided we wanted it white-labeled and customizable for multiple shop owners, and don't know where to begin in implementing these features in an existing application. Any input is appreciated.
edit
To elaborate on multi-tenancy, what I mean - in the context of a store for example, multiple users sign up for their own store at www.mystore.com and are each given a unique subdomain to access their own instance of the store, at user1.mystore.com, user2.mystore.com etc. Each store would have customers with order histories, and those customers would have logins. I would need to restrict customers of user1.mystore.com from logging in at user2.mystore.com without a new account, and likewise prevent user2.mystore.com from accessing user1.mystore.com's customer history.
I implemented a complete MVC multi-tennant app. Here are some links I found handy and some sample apps:
http://msdn.microsoft.com/en-us/library/aa479086.aspx
http://codeofrob.com/archive/2010/02/14/multi-tenancy-in-asp.net-mvc-controller-actions-part-i.aspx
http://www.developer.com/design/article.php/10925_3801931_2/Introduction-to-Multi-Tenant-Architecture.htm
http://msdn.microsoft.com/en-us/library/aa479086.aspx#mlttntda_cc
http://lukesampson.com/post/303245177/subdomains-for-a-single-application-with-asp-net-mvc
http://code.google.com/p/multimvc/
http://www.paulstovell.com/widgets
http://www.agileatwork.com/bolt-on-multi-tenancy-in-asp-net-mvc-with-unity-and-nhibernate/
http://ayende.com/blog/3530/multi-tenancy-approaches-and-applicability
http://weblogs.asp.net/zowens/archive/tags/Multi-tenancy/default.aspx
http://cloudsamurai.codeplex.com/
http://cloudninja.codeplex.com/
http://msdn.microsoft.com/en-us/library/hh534484.aspx
http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx
http://blog.tonywilliams.me.uk/asp-net-mvc-2-routing-subdomains-to-areas
Even starting from scratch, you are in for a world of hurt. The MVC framework does very little to help you address the issues.
Most likely you are about to spend a fair amount of time restructuring your database.
The first step is that you are going to create a table to house your "Tenant" list. Then you need to add this TenantId to just about every table in your system to make sure no one steps on each other. You can skip any tables that are global in nature. One example might be a list of Status Codes.
However, everything from users to the data they have etc will have to have this ID. Also, modify all of your indexes to take tenantid into account.
Once you have that, you'll need to modify all of your queries to take the tenantid into account.
One column of the tenants table should be the portal url. Like customername.oursite.com or whatever. This way you could point multiple urls to the exact same code. When the site needs to use the current tenantid just look it up based on the URL the passed in.
If I was doing this, I'd plan to spend about 1 to 2 hours per table in the database to make it "multi-tenant". Obviously some tables (and their queries) will go faster; others will take longer.
Incidentally, this doesn't cover things like customizing the UI (look / feel) per tenant or anything of that nature. If you need to do this then you'll have to either create a directory on the server for each tenant to hold their style sheets or load it directly from the DB (which has it's own issues with regards to caching).
Typically, you design for this at the beginning of the project. Refitting an already (or almost) complete project is a PITA.
Finally, test, test, test and do more testing. You will have to make sure that every single query pulls only the data it absolutely needs to.
There has been some talk of multi-tenancy support in Sharp Architecture (based on MVC 3) found here: http://www.yellowfeather.co.uk/2011/02/multi-tenancy-on-sharp-architecture-revisited/
Not sure if that really helps you with your existing application, porting over would be a bit of a job.