Sitemap

Protection Proxy Design pattern

7 min readMar 7, 2023

--

The central idea around the Protection Proxy Design pattern is to have a proxy to control access to an object and its individual methods based on conditions, thereby protecting the object from unauthorized access. That gives us an entity trying to access an object, the object itself , and a proxy controlling access to it. We will explore all of them in detail.

Photo by Sakibul on Unsplash

Protection proxies are immensely useful in controlling access to objects, over the wire or otherwise. This can be used to grant write/read/execute access to users of an application. It can also be used to decide whether or not to grant a client access to a service over the wire.

Real life analogy

We will take a real life example of a hotel. Broadly the hotel will have staffs and guests. There will be actions limited to the hotel staffs, like accessing the kitchen area, accessing the monitor room and so on. Similarly, actions like checking into a hotel, checking out, or rating the hotel will be limited to guests.

The real object

Let’s check out the real object first. We have an interface for the real object as shown below. But what is the real object? It is actually the object which in turn has access to all the tasks mentioned above. Think of it like a super user, which can perform all the tasks like accessing the kitchen, checking into a hotel etc, and which a hotel staff or a hotel guest will try to access, to perform the tasks.

public interface HotelPerson {
void accessKitchen();
void AccessMonitorRoom();

void checkIn();
void checkOut();
void rate();
}
public class HotelPersonImpl implements HotelPerson {
@Override
public void accessKitchen() {
System.out.println("Accessing the kitchen");
}

@Override
public void AccessMonitorRoom() {
System.out.println("Accessing the monitor room");
}

@Override
public void checkIn() {
System.out.println("Checking in");
}

@Override
public void checkOut() {
System.out.println("Checking out");
}

@Override
public void rate() {
System.out.println("Rate");
}
}

HotelPersonImpl implements the HotelPerson interface, and has the tasks of accessing the kitchen, accessing the monitor room, checking into the hotel, checking out, and rating the hotel as its methods.

Anyone who has access to the HotelPerson interface has the power to perform(invoke) all these methods.

The proxy and its invocation handler

Between the client and the superuser HotelPerson it is trying to access, sits the proxy setup. The Proxy setup has 2 parts actually- the proxy itself and the invocation handler.

The invocation handler handles things for the proxy. Any time a call to a method is made, the proxy delegates it to the invocation handler. What purpose does this delegation serve? We understand this when we realize that there can be multiple sets of proxy + invocation handler. How many? It depends on the number of types of access required. In our case, there are 2 types of accesses required, a hotel staff access and a hotel guest access. So there will be 2 sets of proxy + invocation handler.

Back to the purpose/delegation part. When a call is made to a proxy, it is actually made to a specific proxy, a staff proxy or a guest proxy. Based on it, that proxy’s invocation handler, to which the proxy delegates the call, will restrict the access to some of the functions. For instance, a call made to a hotel staff proxy(and its invocation handler) will allow it to only access the kitchen and the monitor room , but restrict its access from checking into the hotel, checking out, or rating the hotel. Similarly, a request made to a guest proxy(and its invocation handler) will allow checking into the hotel, checking out, or rating the hotel, but disallow accessing the kitchen or the monitor room.

So the client makes a call to the proxy, and the proxy in turn internally makes a call to the invocation handler, which then decides the access to the individual methods based on who is it itself, whether it belongs to the hotel staff set of proxy +invocation handler or the hotel guest set.

We will check out the code of the invocation handlers, and understand them. Let’s check out the HotelStaffInvocationHandler first.

public class HotelStaffInvocationHandler implements InvocationHandler {
HotelPerson hotelPerson;

//get the HotelPerson interface in its constructor
public HotelStaffInvocationHandler(HotelPerson hotelPerson){
this.hotelPerson=hotelPerson;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

String methodName=method.getName();
switch(methodName) {
case "accessKitchen":
case "AccessMonitorRoom":
//invoke the method that was called on the proxy, but on the CONCRETE hotelPerson
return method.invoke(hotelPerson,args);

case "checkIn":
case "checkOut":
case "rate":
default:
System.out.println("Disallowed task for hotel staffs");

}//switch

return null;
}//invoke
}

Invocation handlers implement the InvocationHandler of the specific language’s Reflection package. In case of Java, it is the java.lang.reflect package.

Get Snigdha Sanat’s stories in your inbox

Join Medium for free to get updates from this writer.

The invocation handlers have an instance of the interface HotelPerson, rather its concrete implementation HotelPersonImpl, in its constructor. That way, it knows who is it protecting.

How does it implement the access part based on which set it belongs to?Essentially it implements the invoke() method of the InvocationHandler interface where it controls the accesses. This method in a way forms the central part of the Protection Proxy pattern.

The invoke method takes arguments of the proxy, the method, and the arguments of the method being tried to be invoked. For instance, we might try to invoke the accessKitchen() method. In that case, the 2nd argument “method” of invoke() is the accessKitchen() method, and the 3rd argument “args” is accessKitchen’s arguments. What is the 1st argument “proxy”? It is the proxy of the invocation handler. If it is a HotelStaffInvocationHandler, it will have a staff proxy, and if it is a HotelGuestInvocationHandler, it will have a guest proxy.

See the definition of the invoke() method. Based on whether it itself is a HotelStaffInvocationHandler or HotelGuestInvocationHandler, and which method is being tried to be invoked, it will then either restrict access to the method, or allow it. The restriction part is fairly straightforward. But the part where it allows is where it gets interesting.

For the methods accessKitchen() and accessMonitorRoom() of HotelStaffInvocationHandler, it lets it pass through. It invokes the method, with method.invoke(), and passes the arg as the 2nd argument, which were the arguments passed to the method. Note the the method.invoke() has the hotelPerson as the 1st argument. This is the instance the invocation handler had received in its constructor, and the actual entity it is trying to protect. At this stage it knows that the staff has access to accessKitchen() and accessMonitorRoom(). So it calls the method on the hotelPerson itself, which is the real object, passing the arguments. That means the proxy delegates the call to the invocation handler( we will see the delegation in a bit), but the invocation handler, knowing whether it is a staff or a guest and which is the method it is trying to access, calls the method on the actual entity, NOT the proxy now, through method.invoke(hotelPerson,args).

We have a similar code for the HotelGuestInvocationHandler.

How does the proxy delegate it to the invocation handler? Let’s check out the code of the proxy HotelStaffProxy, the proxy for HotelStaffInvocationHandler.

public class HotelStaffProxy {
public static HotelPerson getHotelStaffProxy(HotelPerson hotelPerson){
//pass the HotelStaffInvocationHandler class, and the class and
//interfaces of the hotelPerson interface
return (HotelPerson) Proxy.newProxyInstance(hotelPerson.getClass().
getClassLoader(),hotelPerson.getClass().getInterfaces(),
new HotelStaffInvocationHandler(hotelPerson));
}
}

Above, it is creating the proxy with the Proxy.newInstance(), and passing it the hotelPerson’s class, its interfaces, and the HotelStaffInvocationHandler. This is the stage where HotelStaffInvocationHandler gets attached to the HotelStaffProxy. The HotelStaffInvocationHandler knows who it is attached to now(staff proxy or the guest proxy), and so which methods are allowed and which methods are disallowed. This knowledge now is usable by the proxy. The proxy returned by Proxy.newInstance() is what gets used by the client.

Note that the invoke() method of the invocation handler is called internally, when the methods are called from the client. We will see that bit now.

The client

public class Client {
public static void main(String[] args) {
HotelPerson hotelPerson=new HotelPersonImpl();

HotelPerson hotelStaffProxy= HotelStaffProxy.getHotelStaffProxy(hotelPerson);;
System.out.println("Created hotel staff proxy");

System.out.println("Hotel staff trying to access kitchen");
hotelStaffProxy.accessKitchen();

System.out.println("Hotel staff trying to rate the hotel");
hotelStaffProxy.rate();

HotelPerson hotelGuestProxy= HotelGuestProxy.getHotelGuestProxy(hotelPerson);
System.out.println("Created hotel guest proxy");

System.out.println("Hotel guest trying to access kitchen");
hotelGuestProxy.accessKitchen();

System.out.println("Hotel guest trying to rate the hotel");
hotelGuestProxy.rate();
}
}

The Client is simple. It just creates the proxies- hotelStaffProxy and hotelGuestProxy, passing them the HotelPerson instance, which in turn is passed to the invocation handlers. The client then calls the methods thorough these proxies.

What happens internally is that the methods are called through the respective proxies hotelStaffProxy and hotelGuestProxy, and each of them has an invocation handler attached to it. So the respective invocation handlers then know who is trying to access- the staff or the guest, and accordingly decide for each of the methods, whether to provide access or not. If yes- the invocation handler then calls the methods on the actual HotelPerson, through the method.invoke() inside the invoke() method of the invocation handler.

So the client creates the proxies, and the proxies through their respective invocation handler decide the access of the client to the individual methods, thereby protecting them from unsolicited access. And that is the Protection Proxy pattern’s definition:

The Protection Proxy controls access to an object based on access rights, thereby protecting it.

At a glance

Press enter or click to view image in full size

Code examples

The examples used in this article are here.

--

--