开发者

What are the best practices to separate data from users

For a customer we where developing a big application that where open to all users if you will, meaning, all users could see each others data.

Now suddenly the customer is saying that they want only users belonging to the same organization to be able to view each others data.

So we came up with this data model:

What are the best practices to separate data from users

So now the question is: How is it best to separate the data?

This is the only alternative I see:

  • SQL JOIN on ALL relevant tables (All tables that have data should no always join on Organization) -- All queries should now add an extra join to Organization, and if the join doesn't exists, we need to create a new foreign key.

But I feel an extra join (We have around 20 tables that needs extra join) is quite costly.

I hope there are some other best practice开发者_JAVA技巧s or solutions we can consider.

PS: This is a Web application developed using Java/JSF/Seam (but I don't know if that is relevant)

UPDATE

I want to clarify something. My consurn is not security but performance. We have added the foreign key to organization to all relevant tables that has shared data, and we are using user's logged in organization to filter the data.

All I want to know is if this is a good architectural solution (inner join) or if we should do something else (ie: Load all shared data, and filter in memory instead of sql join).


You really have to understand the difference between the persistency layer and the application layer.

It doesn't matter how you define your database tables, as anyone with database access will have access to all the users data. What does matter is how you define the behavior in your application.

Changing the database design should only be done for performance reasons, not for security - which should be handled in the application.


I would reckon that the best pattern would be to only expose the user details through the web application, so at that point its a case of restricting the data exposed to each user. This will allow you to build in the required security inside the application.

Alternatively if you are allowing direct database access then you will need to create a login/user (depends on database used) for each organization or user and then restrict the access of these login/user entities to parameterized stored procedures rather than the base tables. This will push security back onto the database, which is riskier but still do-able.

As to meta changes to support the organization column, parameterizing the stored procedures will be fairly trivial:

select @organizationId = organizationId from User where User.id = @currentUserId

select * from User where organizationId = @organizationId

(depending on the sql flavour you will need to enclose some entities eg ``User, [User] etc)


I see no reason that Organization has to be 'joined' at all.

If your 'data' tables all have OrganizationID columns, then you can lookup the 'organizationID' from the user and then add this as a condition to the join.

EX:

select @OrganizationId = organizationId from User where User.id = @currentUserId
select * from datatable a ....  where .... AND a.organizationID = @organizationID

See; no join.

With respect to performance, there are different types of joins, and SQLServer allows you to hint at the type of join. So in some cases, a merge join is the best, whereas in something like this scenario, a loop join would be the best. Not sure if these choices are available in MySQL.

With respect to all of your tables needing a join, or condition (see above), there is a logical answer, and an implementation answer. The implementation answer depends on your indexing. If you can limit the dataset the most by adding that condition, then you will benefit. But if the join with the other table that has already been filtered does a better job at reducing rows, then the condition will be worthless (or worst case, it will use the wrong index). Assuming you have indexes on your join and condition columns.

Logically, only data that isn't fully dependent on a table that is filtered by organizationID needs that extra condition. If you have a car table, and carparts table, then you only have to filter the car table. Unless for some reason you don't need to join with the car table for some joins, in which case you will need that organizationID on the parts table too.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜