Re: Restricting functionality on objects: "remote access proxy" (pattern)
- From: "H. S. Lahman" <h.lahman@xxxxxxxxxxx>
- Date: Fri, 17 Aug 2007 15:44:38 GMT
Responding to Wutzke...
<snip example>
How do you restrict access for a real chat room on the network by
using the current (or another user's) level/permissions (there are
admins, mods, owners, ops, normal users)?
1. The easiest way is probably not to expose functionality via the
GUI, so users with admin level will see a popup with more entries than
a regular chatter. However this is no real security concept. Accessing
the model objects can still produce an unwanted command (e.g. by some
artificial instance not having a GUI at all).
I don't buy this argument, at least directly. The subsystem or layer where this object exists will have an interface for communicating with the outside world that will be shared by all "users", whether they be a person at a GUI or another chunk of software. That interface will have a DbC precondition to ensure that the external context for invoking that interface element is valid. IOW, it is not this subsystem's responsibility to check if its clients are doing their jobs correctly.
OTOH, prudence suggests that software should be able to detect when it is broken and cannot continue processing properly. So it is valid for the subsystem to have correctness assertions that can detect if the client has lost its mind and signal an exception if it has. So...
2. The list of commands generated via some CommandFactory (the objects
that would do something when a button gets pressed) is limited by the
user's (or some other) level. A normal user can't instantiate a
"BanCommand" for example. The command objects act as messenger
objects, but nevertheless those objects would still call the public
unfiltered methods on that interface.
You could use the Command pattern to check privileges, but that is a pretty complicated way to do a simple task.
3. Somehow provide different implementations of that interface by
subclassing (or else) and throwing some exception for those operations/
method calls that are not allowed with the current user's level. A
normal user calling myChat.ban(otherUser) would get such an exception.
Disadvantage of subclassing here would be, that I'd need one subclass
per user level (admin, moderator, owner, operator, normal). In case
the user's level gets upgraded, the instance/s of such chats would
have to be replaced. Looks like bad design to me.
This is close but a better idea is to provide different interfaces to the object and only expose the less privileged clients to the interface elements they have a right to access. That, though, becomes difficult when the client is external to the subsystem, like a GUI. One would need to provide the right subsystem interface to the client, but which one is right will depend on who is logged in.
The simplest way is to allow each user to identify themselves and provide a privilege bitmap for each user from a separate <secure> configuration source. There are many ways to do that, so the following is only one possibility:
* creates R1 1
[UserSurrogate] ---------------- [UserFactory]
+ privilegeBitmap
| *
| accessed by
|
| R2
|
| *
[Chat]
+ getName()
+ setName()
+ getOwner()
+ setOwnder().
When a UserSurrogate is instantiated by the factory object (presumably when someone logs into a chat session), the factory object goes to a DB and looks up the privilegeBitmap for that particular user identifier to initialize it. For accessors like getName and getOwner the privilege doesn't matter so they don't do anything special. However, the setName and setOwner accessors will access the privilegeBitmap and check if their bit in it is set of not. If not, they generate and exception.
So what's wrong with this picture? The R2 relationship is *:*, so how does a Chat know which UserSurrogate to access to get the bitmap? The obvious and simplest way is for UserSurrogate to pass its bitmap value in the message that it sends to Chat (e.g., setName(name, bitmap)). Note that passing the bitmap is fine because that is under the control of the subsystem in hand and it forces the mapping of privileges to Just Work because it controls the initialization of privilegeBitmap.
[Caveat: passing the bitmap value is not the most robust solution from a maintenance viewpoint, but I wanted to keep the example simple.]
Instead of subclassing one could also implement this via several
Strategies, one per method. I believe the "Bridge" pattern could be
applied as well, for dynamic method implementations.
In any way, I started creating a concrete subclass of a Chat interface
called "ChatProxy" which is supposed to
handle the communication with the actual chat server (no
implementation yet). Maybe that is supposed to be the class where the
restrictions belong. Such a proxy might act as an "access proxy" but
also as a "remote proxy".
Note that UserSurrogate is essentially a proxy for the external user. It is just less complicated than the GoF pattern because there is no exotic dynamic substitution required here. When a message comes from GUI (or whatever) is will contain an identifier for the actual user. The subsystem interface will then redirect that message to the right UserSurrogate object who will then talk to other objects as needed.
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
hsl@xxxxxxxxxxxxxxxxx
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@xxxxxxxxxxxxxxxxx for your copy.
Pathfinder is hiring: http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
.
- Follow-Ups:
- Re: Restricting functionality on objects: "remote access proxy" (pattern)
- From: Karsten Wutzke
- Re: Restricting functionality on objects: "remote access proxy" (pattern)
- References:
- Restricting functionality on objects: "remote access proxy" (pattern)
- From: Karsten Wutzke
- Restricting functionality on objects: "remote access proxy" (pattern)
- Prev by Date: Looking for C++, OOPs Professionals (Bangalore)
- Next by Date: Re: Everything
- Previous by thread: Restricting functionality on objects: "remote access proxy" (pattern)
- Next by thread: Re: Restricting functionality on objects: "remote access proxy" (pattern)
- Index(es):