2009-01-11 9 views
5

Ich habe darüber jetzt zu viel nachgedacht, ohne offensichtlich korrekte Lösung. Es könnte eine echte Holz-für-die-Bäume-Situation sein, also brauche ich stackoverflow-Hilfe.Wie man den Datenbankzugriff entsprechend den Anwendungsanwenderattributen einschränkt oder filtert

Ich versuche, Datenbankfilterung auf regionaler Basis zu erzwingen. Mein System hat verschiedene Benutzer und jeder ist einem regionalen Büro zugeordnet. Ich möchte nur, dass Benutzer Daten sehen können, die mit ihrem regionalen Büro verknüpft sind.

Einfach gesagt meine Anwendung ist: Java App -> JPA (Hibernate) -> MySQL

Die Datenbank enthält Objekt aus allen Regionen, aber ich möchte nur die Benutzer in der Lage sein, Objekte aus der eigenen Region zu manipulieren. Ich habe über die folgenden Möglichkeiten, es zu tun:

1) ändern Sie alle Datenbankabfragen, so dass sie etwas wie Select * aus Tabellex wo Region = "myregion" lesen. Das ist eklig. Es funktioniert nicht gut mit JPA zB die Methode entitymanager.find() akzeptiert nur Primärschlüssel. Natürlich kann ich native gehen, aber ich muss nur eine Select-Anweisung verpassen und meine Sicherheit wird geschossen

2) Verwenden Sie einen MySQL-Proxy, um Ergebnisse zu filtern. irgendwie funky, aber dann sieht der mysql proxy nur den rohen call und weiß nicht wirklich wie er sie filtern soll (dh in welcher region der benutzer, der diese anfrage gemacht hat). Ok, ich könnte einen Proxy für jede Region starten, aber es beginnt ein wenig unordentlich.

3) Verwenden Sie separate Schemas für jede Region. Ja, ich benutze Spring, damit ich die RoutingDataSource verwenden kann, um die Anfragen über die richtige Datenquelle (1 Datenquelle pro Schema) zu routen. Natürlich ist das Problem jetzt irgendwo auf der Linie, ich werde nach Region und einer anderen Kategorie filtern wollen. ohs.

4) ACL - nicht wirklich sicher darüber. Wenn a hat eine Auswahl * von tablex; Würde es Objekte, für die ich keinen Zugriff habe, ruhig ausfiltern oder würde eine Menge von Zugriffsausnahmen ausgelöst werden?

Aber denke ich zu viel darüber nach? Dies scheint ein wirklich häufiges Problem zu sein. Es muss eine einfache Lösung geben, ich bin einfach zu dumm um es zu sehen. Ich bin mir sicher, dass es etwas in der Nähe der Datenbank oder in der Datenbank sein wird, da Sie so nah wie möglich an der Quelle filtern möchten, aber was?

Nicht suchen, spoonfed zu sein - irgendwelche Verbindungen, Schlüsselwörter, Ideen, kommerzielle/opensource Produktvorschläge würden wirklich geschätzt !! Vielen Dank.

+0

Dies scheint eine der Situationen zu sein, in denen es sich ausgezahlt hat, Ihre eigene DAL zu schreiben, aber ich denke, dass es für Sie nicht in Frage kommt. Es scheint, dass Sie sie auf der Geschäftsebene heraus filtern müssen. Große Frage, ich hoffe, dass jemand hier mit einer guten Antwort kommt. –

+0

Zum Glück habe ich eine sehr saubere DAL ... also # 1 sieht aus wie der Weg nach vorne. Ich möchte nur in der Lage sein, die Nutzung der DAL zu erzwingen, da ein Entwickler in der Zukunft entscheiden könnte, es zu umgehen. –

Antwort

1

Ich habe gerade etwas Ähnliches (REALbasic im Gespräch mit MySQL) in den letzten Wochen für eine hierarchische Multi-Firma-Erweiterung zu einem Buchhaltungspaket implementiert.

Es gibt eine große Menge an existierendem Code, der SQL-Anweisungen zusammenstellt, also mussten wir damit leben und eine Menge Auditing durchführen, um sicherzustellen, dass die Einschränkungen in jeder Tabelle entsprechend enthalten sind.Ein Fehler war verwandte Lookups, wo Lookup-Tabellen normalerweise nur in Kombination mit einer primären Tabelle verwendet wurden, aber für einige Wartung GUIs würde die Lookup-Tabelle selbst direkt laden.

Es besteht die Gefahr des Gebens implizierten Informationen weg wie aufschlussreich, dass Acme Pornostars ein Kunde von einem gewissen Bereich des Unternehmens sind ;-)

Die einzige Lösung für diesen Teil war sehr sorgfältige Konstruktion der DB-Diagramme alle zeigen implizierte Beziehungen und viele Auditing- und Grepping-Quelltexte, mit sorgfältiger Kommentierung, um Bereiche anzugeben, in denen keine zusätzlichen Einschränkungen erforderlich waren.

Das einzige Muster, das ich habe, um dies in Zukunft verallgemeinert zu machen, ist, statt explizite region = currentRegionVar Typ sucht, mit einer beliebigen EntityID, die von einer globalen CurrentEntityForRole ("blah") -Funktion geliefert wird.

Diese Abstraktion ermöglicht die gemeinsame Nutzung einiger Daten sowie die Implementierung von Pseudo-Entities, die andere Restriktionsgrenzen darstellen.

Ich weiß nicht genug über Java und Spring in der Lage zu sagen, aber gibt es eine Möglichkeit, Ansichten zu verwenden, um eine Single-Key-Lookup bereitzustellen, wo die Ansichten durch den Regionsfilter eingeschränkt sind?

Der Wunsch, Aggregationen und mögliche gemeinsame Nutzung von Daten bereitzustellen, war der Grund, warum wir die separate Datenbankroute nicht heruntergefahren haben.

+0

Ich komme zu dem gleichen Schluss ... Ich werde nur alle direkt/indirekt erfassen müssen SQL-Anweisungen. Könntest du etwas darüber erzählen, wie du deine CurrentEntityForRole() -Funktion benutzt - ich bin mir nicht ganz sicher, ob ich das verstehe? –

+0

"WHERE accounts.corpEntityID =" + CorporateEntities.IDforRoleQuoted ("accounts") ermöglicht eine andere Entität als die des aktuellen Benutzers. Sagen Sie, dass Unternehmen und Abteilungen Kontenpläne teilen - eine Abteilung erhält die ID ihrer Muttergesellschaft. Es bildet CurrentID + Role => effectiveID ab. Selten benutzt, aber nützlich. –

+0

hab dich! - Vielen Dank –

1

Gute Frage.

Scheint wie # 1 ist das Beste, da es am flexibelsten ist.

Region ist, was Sie heute filtern, aber es könnte Region + Abteilung + Farbe der Haare morgen sein.

Wenn Sie anfangen, die Daten zu sehr zu zerlegen, scheint es, als würden Sie fest daran arbeiten, härter als nötig zu arbeiten, um sie alle für das Reporting wieder zusammenzukleben.

0

Ich habe das gleiche Problem. Es ist schwer zu glauben, dass eine solche allgemeine Aufgabe (Filtern einer Liste von Modell-Entitäten auf der Basis des Benutzerprofils) keine "Standard" -Methode, kein Muster oder keine Best Practice dafür hat.

Ich habe pgacl gefunden, ein PostgreSQL-Modul. Im Grunde genommen führen Sie Ihre Abfrage so aus, wie Sie es normalerweise tun würden, und dann wenden Sie das Prädikat acl_access() an, um als Filter zu arbeiten.

Vielleicht gibt es etwas Ähnliches für MySQL.

0

Ich empfehle Ihnen, ACL zu verwenden. Es ist flexibler als andere Wahlen. Verwenden Sie Spring Security. Sie können es verwenden, ohne Spring Framework zu verwenden. Lesen Sie das Tutorial von link text