如何将单用户WebApp扩展到多个用户 [英] How to expand single user WebApp to multiple users

查看:135
本文介绍了如何将单用户WebApp扩展到多个用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类似的线程没有具体的解决方案,我认为最好开始一个新的线程.

There are a similar threads without a concrete solution and I thought it was better to start a new one.

我正面临着在RESIN中托管WebApp的情况(就像我猜想的Tomcat).到目前为止,由于我是一个人,因此我一直在使用db4o开发该应用程序,我需要尽快完成该应用程序,我有一个用于用户的数据库和另一个用于单个用户(me)的应用程序数据的数据库,现在该应用程序几乎我将要迁移到postgresql,并且即使数据库中包含多个应用程序的数据,我也会认真考虑每个用户的数据库,因为它会处理一些机密数据,我认为最好使用单独的数据库(从安全角度考虑).已经有一个基本的会话管理,可以将用户数据(例如ID)存储在浏览器中.但是我想知道如何将其扩展到多个用户/数据库.

I am facing a situation where I have a WebApp hosted in RESIN (just like Tomcat I guess). So far I have been developing the app using db4o since I'm alone and I needed to complete the app ASAP, I have a DB for users and another DB for app data for a single user (me), now that the app is almost done I'm about to move to postgresql and I am thinking seriously about a DB per user even if the DB holds data for multiple apps since it will handle kinda confidential data and I thought having separate DB will be the best (security wise). There is already a rudimentary session management that stores user data like an ID in the browser. But I was wondering how can I expand it to multiple users/db.

我当时正在考虑扩展侦听器类,以保留上下文数据,以将正确的db对象传递给应用程序实例,或者为此目的设置过滤器.

I was thinking to expand the listener class that keeps the context data to pass the right db object to the app instance, or maybe set a filter for that purpose.

.UPDATE.

我想对自己目前拥有的东西有更多的了解.

I wanted to give some more insight of what I currently have.

我有:

保存对某些对象的引用的上下文,这些对象之一连接到数据库并检查用户名和密码.

Context that holds a reference to some objects, one of those objects connects to a DB and checks for the user and password.

映射到"/"的演示文稿Servlet(HttpServlet)具有POST到/login的登录形式.

Presentation servlet (HttpServlet) mapped to "/" that has the login form that POST to /login.

映射到"/login"的登录servlet(HttpServlet),用于根据Context中驻留的各个对象检查httpSession用户密码属性,如果存在匹配项,则会设置一个保存USERID并将用户重定向到应用本身位于/index-debug.html(如果没有),则会再次创建一个带有登录表单的新html页面.

Login servlet (HttpServlet) mapped to "/login" that checks the httpSession user password attributes against the respective object that rests in the Context, if there is a match sets an httpSession attribute that holds the USERID and redirects the user to the app itself located at /index-debug.html if not it creates a new html page with a login form again.

映射到/index-debug.html的授权和身份验证过滤器,该过滤器验证USERID属性的httpServletRequest并检查用户是否有权访问该应用.

Authorization and authentication filters mapped to /index-debug.html that verifies the httpServletRequest for the USERID attribute and checks whether or not the user has permission to access the app.

最后是一个负责读取和写入WebApp用户数据DB的DB Bean.当我在webApp中执行某些方法时,CP2JAVAWS将该方法与Bean中的相应方法进行匹配,问题是该Bean具有静态数据库,并且到目前为止它仅允许一个用户使用.

Finally a DB bean that is in charge of reading and writing to the webApp user data DB. When I execute certain method in the webApp CP2JAVAWS matches that method to the respective method in the bean, the problem is that this bean has a static database and so far it only allows one user at the time.

我想做的就是以某种方式允许该DB bean为每个用户实例化一次,并根据当前登录的用户读取和存储相应的数据.

What I would like to do is somehow allow this DB bean to instantiate once per user and read and store the corresponding data depending of the current logged user.

每个用户一个数据库的想法目前已被放弃,但我不知道该如何实现.

The idea of one DB per user is currently discarded but I don't know how exactly pull that off.

推荐答案

您提到了Postgres作为数据库后端,它具有称为架构的功能.这是您在其中具有一个物理数据库和多个架构的情况.我的经验来自Rails,但是概念是相同的.此方法避免将人们的数据混在一起放在同一组表中,这听起来像是您最关心的问题.我知道您使用的是Java,但

You mentioned Postgres as the database backend and that has the feature called schemas. This is something where you have one physical database and multiple schemas inside the database. My experience with this comes from Rails, but the concepts are the same. This method avoids mashing people's data together in the same set of tables which sounds like your primary concern. I know you're using Java, but watch this talk on Multi-tenant apps in Rails to get a background from Guy Naor on how this works, trade-offs, etc.

以下是一些具体步骤,可帮助您着手使用Postgres模式:

Here are some concrete steps to get you started down this path of using Postgres schemas:

  1. Postgres中有一个默认的公共模式.您将在此处放置用户身份验证表以及有关用户登录等的任何其他通用元数据表.
  1. There is a public schema in Postgres that is the default. This would be where you put your user authentication tables and any other generic meta-data tables about user logins, etc. See Postgres docs for more info on how schemas work
  2. Come up with a naming convention for each schema you will create (e.g. user_001, user_002, etc.). Pre-allocate a bunch of empty schemas with all the tables setup and when the user registers or logs in for the first time, you assign them a schema and store the schema name in their user record in the public schema and in the user object that you have in HttpSession. There would be no need to run table creation scripts for a first time user - that would be a performance drag in a web app. You just need to stay ahead of the rate of new users. For example you could have a bunch of empty user_standby_1 ... user_standby_100 schemas and then when someone logs in or registers, you would run this sql:

myquery = "ALTER SCHEMA user_standby_? RENAME TO user_?"; myquery.setString(1,standby_id); myquery.setString(2,user_id);

myquery = "ALTER SCHEMA user_standby_? RENAME TO user_?"; myquery.setString(1,standby_id); myquery.setString(2,user_id);

在创建数据库bean时(为此使用超类,请参见下文),从HttpSession传递User对象的模式名称,然后在执行每个操作之前执行此SQL,以仅将它们隔离到其模式:

When you create your DB bean (use a superclass for this, see below), pass in the schema name from the User object from the HttpSession, then execute this SQL before every operation to isolate them to their schema only:

myquery2 = "SET search_path TO ?";
myquery2.setString(1,user.search_path);

myquery2 = "SET search_path TO ?";
myquery2.setString(1,user.search_path);

如果在public中有一个空的完整模式,则要从搜索路径中省略public,否则您将在搜索路径中有2个具有相同名称的表.如果要让用户搜索路径包括SET search_path TO user_001,public,则在创建表之后,请从公共位置删除所有数据表,而不是用户和所需的任何元信息.

If you have an empty full schema in public, then you want to omit public from the search path otherwise you will have 2 tables with the same name in the search path. If you want the users search path to include SET search_path TO user_001,public then after creating tables, drop all the data tables from public other than users and any meta-info you need.

如果您走替代路线,并且将所有用户数据都放在一组表中,那么最好的方法是在 every 表中包含user_id并编写您的SQL以使用该 every 时间.如果您使用传统的规范化并进行联接以获取user_id,那么最好确保您不会意外错过联接,否则用户将开始看到彼此的数据.

If you go the alternative route and have all users data in one set of tables, then the best approach is to have user_id in every table and write your SQL to use that every time. If you use traditional normalization and do joins to get your user_id, then you better make sure you don't accidentally miss a join or users will start seeing each others data.

Postgres模式功能允许您锁定用户仅对其自己的数据的访问权限.在弄清基础知识之后,使用Java中的超类编写上面的步骤3,以便每个MyTableDBBean都从MasterDBBean扩展出来,并使用超类构造函数将搜索路径隔离到用户的架构.这样一来,您的代码中只有1个位置可以完成此操作,您不必为每个表或查询记住所有要做的事情,而不仅仅是业务逻辑.

The Postgres schema feature allows you to lock users access to only their own data. After figuring out the basics, use a superclass in Java to write step 3 above so every MyTableDBBean extends from MasterDBBean and uses the super class constructor to isolate the search path to the user's schema. Then you only have 1 place in your code where this is done and you don't have to remember for every table or query to do anything more than the business logic.

这篇关于如何将单用户WebApp扩展到多个用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆