Design pattern or approach for controlling access to object fields

As you know, in many OO programming languages ​​we can use some access modifiers to specify the access area of ​​the fields inside the object.

for example, in java we can use public, protected or private to specify the access area for the field for all callers for this object.

but my question is that I want to specify different permissions for the called party for different callers.

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

for example, suppose a chess game has at least 3 objects, 1 chessboard and 2 players, I want the player on the side to “read” access to all chess on the chessboard, to move “access to all black chess (and only "move" directly when he in turn), and vice versa.

I already had some ideas, as shown below, but it seems that these ideas are too complex and not ideal.

is there a good approach, design template or something else to deal with this problem?

thank you very much

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

my ideas:

access key class 1.use.

  • enter the class access key.
  • use the game host class to assign a key instance to different players.
  • A chessboard class instance has a table with key rights.
  • each time the player performs the action “read” or “move” to the side, he must provide his key example as a parameter for the method, if permission is rejected, an exception is thrown.

2.use the broker management class

  • inside the checkerboard there is an internal class "boardcontroller".
  • 2 is a subclass of the BoardController class, 1 can move white chess, and the other can move black chess.

(although I can use some if-else in this subclass to decide that it can move some chess or not, but I want the player class to be written by another programmer and let them write their AI, so the resolution flow of judgment used by this subclass cannot be used directly in the player’s class as an approach to my question.)

  • Assign the instance of the subcontroller to another player.

3.low level approach (ugly and not perfect)

in the “move” or “read” method of the board class, check the flow column to see if the caller is in the “player” class and which side (black or white).

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

any better idea? thanks

+5
source share
4 answers

A proxy is what you need.

This design template controls access to a specific object, can control their creation or something.

The best part is that the client does not know that he is using a proxy. Only part, if the method of calling clients to which it does not have access, can cause some kind of exception. In this case, you need to change the class interface for each such method in order to throw an exception, the actual implementation will not do this, but for a proxy server this is a good solution.

Link

+4
source

No matter how you set it up, you have the opportunity by passing it with reflection or your own code.

The only safe way is for the components to work in their own process, so they do not have direct access to each other. They can work as services, filter who receives them, and limit what operations can be performed. Even this is not completely safe.

However, if you use the passkey through a method call, you accept the level of trust. If you are ready to accept the level of trust, then perhaps you could consider a simpler model. that is, I'm not sure what level of trust the access key will be the right amount of security.

+2
source

design pattern or approach to controlling access to the field of object objects

Each type specifies access control to fields and methods through private , protected , public or just a package. Another class can only call methods or get field values ​​if it has access to another object - a link. Thus, you must control who can get a link to an object.

Even if a proxy server is often an access control solution, you can also make access rights rules clear in design.

For a chess game, I first developed an interface called ChessPiece . Since each player can see all fragments of chesss, I would indicate 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 create a chessboard that gives access to all ChessPiece s.

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

A Player has access to the chessboard and thus can see all the pieces. But a Player is only allowed to move its 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 the player can only move his 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. The method belongs to the class, and the object is an instance of some class. Someone can only call the method if you have access to the object (link). Thus, access rights can simply be represented by objects that position the prospect of access to other objects. You only need to make sure that the correct link is provided to the client.

Of course, someone can hack into objects and gain access to private fields using reflection. This can be prevented by installing a security manager .

+1
source

Perhaps this access control design pattern will be the solution: https://www.javaworld.com/article/2075599/java-security/access-control-for-partial-exposure.html

This is an example from an article that uses a template:

 // ******** VirtualMethod ******** public abstract class VirtualMethod { public abstract void call(); } // ******** Server ******** public class Server { private void shakeRattleAndRoll() { System.out.println("SHAKE ... RATTLE AN' ROLL!!!"); } private class ShakeRattleAndRoll extends VirtualMethod { public void call() { shakeRattleAndRoll(); } } public Client getClient() { return new Client(new ShakeRattleAndRoll()); } } // ******** Client ******** public class Client { private VirtualMethod shakeRattleAndRoll; public Client(VirtualMethod shakeRattleAndRoll) { this.shakeRattleAndRoll = shakeRattleAndRoll; } public void demonstrateAccess() { shakeRattleAndRoll.call(); } } // ******** Test ******** public class Test { public static void main(String[] args) { Server server = new Server(); Client client = server.getClient(); client.demonstrateAccess(); // Prints out: SHAKE ... RATTLE AN' ROLL!!! } } 
+1
source

Source: https://habr.com/ru/post/1239618/


All Articles