问题
i am working on a project which is same for several companies, so we have created different databases for different companies with same db structure, each db has it's own identity tables, roles based menus, role based access permission.
I have written a single api to connect different databases based on username supplied. as all company logins with same login screen.
we decide which db to connect by username passed on loginscreen.
Example : 3 companies- abc.com,pqr.com,xyz.com single login screen - www.example.com/login on login screen users will login with their company email user@abc.com,user@pqr.com,user@xyz.com
everything will work well after login
The problem is: jwt token path always connects to abc.com databases to it always display error message for user@pqr.com and user@xyz.com although these records are in their dbs.
Note 1) in future companies will be increasing as these are our portal's customers in future dbs will be - abc.com,bcd.com,def.com....... etc.
2) company owners may have multiple companies also with different dbs, so they need to see reports from both dbs. like Mr X owns 2 companies (abc.com & pqr.com) he may need to see few reports which will need data for both dbs, although company owner has different account in different db.
All issues solved except below one after doing this : I have replaced //var userManager =context.OwinContext.GetUserManager(); with
var appDbContext = new ApplicationDbContext(context.UserName); HttpContext.Current.GetOwinContext().Set(appDbContext); HttpContext.Current.GetOwinContext().Set(new ApplicationUserManager(new Microsoft.AspNet.Identity.EntityFramework.UserStore(appDbContext))); var userManager= HttpContext.Current.GetOwinContext().GetUserManager();
in class - ApplicationOAuthProvider
Note no 2 is not done.## - any help is appreciated
I am looking for permanent solution i am confused. Any assistance is highly appreciated.
回答1:
Yes you can
1) You SHOULD be prepared to configure trust across multiple virtual/physical servers. That's the main advantage of the JWT, that it can be federated. This is irrespective of the databases beyond the web application(s). If you are going to have more than one web server for this application, they need to trust each other.
I believe you can try one of:
i) Have your authentication server coded/configured to be trusted by domains/machines in your solution
see https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/
Particularly note the Audience and Authority strings, and research around these concepts.
ii) Treat an external JWT as a proper "external" credential (like Google OAuth), and then initialise a local JWT or other security mechanism after being referred the external token. I'll have to find references for this.
2) You SHOULD have a separate sub-domain for each customer (see further below after the horizontal rule)
3) You MUST fix your strategy for initializing the DB context. The GetOwinContext method is a terrible implementation of an IoC pattern. The default JWT UserManager code expects the db context to be derived from the OwinContext singleton reference. If you're accessing multiple databases this is a problem. One way is to simply construct the context on demand for now, and think of ways to optimise reuse and performance later. This is probably important because you need to ensure it's checking the correct database for any given query.
Here's one solution link: How to change database name in dbcontext connection string at runtime
4) You have customers who need to access more than one database. There are a few ways to do this. Ideally, you maintain the federated pattern as much as possible. But you also might want/need server-side orchestration: special APIs beyond CRUD which are specialised for multi-db tasks. You would have a server-side action per fixed report. Such a server-side action would look at the request for the databases to query for (in terms of CustomerID), it would verify access via a custom JWT claim (a set of CustomerIDs), it would throw an exception if any specified customerids are not permitted. Then the function would execute as desired with those validated customerids in reference. See [5] for how it could run.
Here are a few links for creating custom JWT claims (these are stored in the JWT, transmitted to and from the client via the Bearer header [usually]):
- https://stackoverflow.com/a/43370327/887092
Here are a few links for getting custom JWT claims:
- Get custom claims from a JWT using Owin
5) It's common to sort a union set of data. This might be the case for you. If the databases are on the same RDBMS instance, it's usually feasible to run a multi-database query in one SQL statement (for SQL Server). (However, if you're using an Azure Database Pool they are generally though to be running on different instances (transparently). I believe there is a recent change which either allows you to specify they be on the same instance, or they now allow multi-database queries). Otherwise, the server-side orchestration means you'll get a top-10 from each database separately, then perform a final sort and top-10 to send back to the client. Worst case, you'll need the client to query multiple times, once for each customerid/database, then on the client side aggregate the data.
(I have covered quite a few points, please let me know which you would like further detail on)
I like database-per-customer
You seem to be describing a system where there is a separate database per customer. When you will be dealing with customers who have no in-app need for sharing data: this is a design I am a big advocate for. It isolates data access (security/privacy), reduces table locking contention (performance), and enables you to move the database(s) to different servers for proximity and load balancing (performance).
all company logins with same login screen.
This requirement is your biggest hurdle. If you've ever used Slack, you'll notice that they set up a new subdomain for each team. There's no need for each team to share credentials.
This design of having separate subdomains means:
- The web server is also a portable component; in addition to the database.
- The customer can setup their own DNS record as a vanity URL (ie. yourapp.acmeco.com); as well as your own default subdomain (ie. acmeco.yourapp.com)
Regardless of the answer to your specific problem, I highly recommend you talk to the stakeholders of your project to see if the multiple subdomain design can be achieved.
For easy configuration (defer to web application), I highly recommend:
- Set up a wildcard DNS record (I know this is supported at least with CloudFlare)
- You SHOULD get a wildcard SSL certificate so it's easy to encrypt every subdomain. That should cost you around $100 for 1-2 years. Don't pay for more features, they're a waste of money IMO.
- Configure you webserver without a specific Host. (If you have other web applications configured alongside with the same IP, they can have a hostname still and share port 80/443). With IIS, that simply means leaving the Host URL area blank.
- You'll need your application to process the JWT/Session to check what database to connect to. On login, you need to check the Host header to determine which database to connect to.
来源:https://stackoverflow.com/questions/51202172/multi-databases-with-own-identity-tables-should-connect-with-single-web-api-and