Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

a design pattern or approach to handle access control of the fields of an object

as we know,in many OO program language ,we can use some access modifiers to specify the access scope of the fields inside an object .

for example, in java we can use public,protected or private to specify the access scope of a field ,for all of the caller to this object .

but my question is that ,I want to specify different access permissions of a callee , for different callers.

the most important point is: the caller class could be written by other programmers, but after my main program is written, they can not change the permission by their own implementation.

for example ,suppose there are at least 3 entities in the chess game program, 1 chessboard and 2 players , I want let the Black side player have "read" access right to all of the chess on the chessboard,but just "move" access access right to all of the black chess,(and only have "move" right when it's in his turn) , and vice versa .

I have already had some ideas as below,but It seems that these ideas are too complicated and not ideal.

so is there any good approach、design pattern,or something else to deal with this problem ?

many thanks

//===============================================================

my ideas:

1.use access key class.

  • make a class "access key".
  • use a "game hoster" class to assign "key" instance to different players.
  • the chessboard class instance has a key-right map table.
  • each time the player do the "read" or "move" action toward the board,it must give their key instance as a parameter to the method, if the permission is denied ,exception thrown .

2.use mediate controller class

  • there is an inner class "boardcontroller" inside the chessboard.
  • 2 sub-class of boardcontroller,1 can move the white chess,the other for black chess.

(although I can use some if-else in this sub-class to decide it can move some chess or not ,but I want let the player class be written by other programer,and let them write their AI,so the permission judgement flow used by these sub-class can not be used directly in the player class as a approach for my question.)

  • assign the sub-boardcontroller instance to different player.

3.low level approach(ugly and not ideal)

in "move" or "read" method of the board class,check the callstack of the thread ,to know is the caller belong to the class "player", and which side(black or white) it is.

//===================================================================

any better idea? thank you

like image 951
柯鴻儀 Avatar asked Jan 01 '16 08:01

柯鴻儀


3 Answers

No matter how you set this up, you have the option of by passing it with reflection or native code.

The only safe way is to have the components run in their own process so they have no direct access to each other. They can run as services, filtering who is accessing them and limit what operations can be performed. Even this is not completely secure.

However, if you use an access key via a method call you are assuming a level of trust. If you are willing to assume a level of trust then perhaps you could consider a simpler model. i.e. I am not sure what level of trust an access key would be the right amount of security.

like image 35
Peter Lawrey Avatar answered Nov 15 '22 00:11

Peter Lawrey


a design pattern or approach to handle access control of the fields of an object

Every type specifies access control to fields and methods via private, protected, public or package only. Another class can only call methods or get field values if it has access to another object - a reference. Thus you must control who can get a reference of some object.

Even if a proxy is often a solution to control access you can also make access right rules explicit by design.

For the chess game I would first design an interface called ChessPiece. Since every player can see all chesss pieces I would specify a method that returns the position of a chess piece.

public interface ChessPiece {
    public Position getPosition();
}

All chess pieces are placed on a chessboard. So the next step is to design a chessboard that gives access to all ChessPieces.

public interface Chessboard {
    public Collection<ChessPiece> getChessPieces();
}

A Player has access to the chessboard and thus can see all pieces. But a Player is only allowed to move his own pieces. Thus a Player must have access to a special kind of chess piece.

public class Player {

    private Collection<PlayersChessPiece> ownPieces;
    private Chessboard chessboard;

    public Player(Chessboard chessboard, Collection<PlayersChessPiece> ownPieces){
        this.chessboard = chessboard;
        this.ownPieces = ownPieces;
    }
}

Since a player can only move his own chess pieces I put this aspect into the design.

public interface PlayersChessPiece extends ChessPiece {
    public void move(Position position) throws MoveNotSupported;
}

The idea behind this design is simple. A method belongs to a class and an object is an instance of some class. Someone can only call a method if one has access to an object (a reference). Thus access rights can be simply represented by objects that put an access right perspective on other objects. You only have to make sure that the correct reference is given to a client.

Of course someone can hack objects and access private fields using reflection. You can only prevent this by installing a security manager.

like image 32
René Link Avatar answered Nov 14 '22 23:11

René Link


Proxy is what you need.

This design pattern is controlling access to a specific object, can control their creation or anything.

Best part about it is that client has no idea that he is using a proxy. Only part is if client calls method that it has no access of you can throw some exception. In this case you have to modify class interface for each such method to be throwing exception, actual implementation wont do it, but for the sake of proxy this is good solution.

Reference

like image 104
8bra1nz Avatar answered Nov 14 '22 23:11

8bra1nz