fbpx

The proxy structural pattern introduces another object that your code uses instead of the actual object. This might seem pointless but there are some good reasons why you might consider this.

Most design pattern references list four reasons why you might want to use a proxy. I explain three of them and then put the fourth in a separate explanation because I think the fourth reason can lead to a security vulnerability if implemented wrong.

  1. The real object might be big or slow to create. Maybe this object is only used rarely in your application. Or maybe it’s always used but just not right away. If you use a proxy, then you can let the proxy create the object when it needs to.
  2. The real object might not exist on your local computer at all. Or if it does exist on your local computer, it might live in another process that’s isolated from your application. A proxy allows you to work with the object as if it’s readily available nearby.
  3. You need to do some extra work when accessing the object such as coordinating access from multiple users.

Most of the documentation that describes the proxy pattern actually mentions another common scenario to control access to an object. Maybe you want to verify if the calling code is actually allowed to use the object. Any object responsible for security needs to be protected and reliable. Now typically, a proxy runs in an application right along with the other code. If you put the proxy on some user’s computer, then it’s under that user’s full control. Now granted, most users won’t know what to do with this or how to exploit the vulnerability. But it only takes one user to figure out that all they need to do is change a little bit of code to bypass the authorization and always make the call to the real object to perform the work. If you’re going to use a proxy to control access, then you either need to duplicate that access check in the real object or make sure the proxy can’t be bypassed.

Implementing a proxy is fairly straightforward. Since it needs to be used in place of the real object, it needs to have the same interface as the real object. Ideally, the code using a proxy shouldn’t know that it’s using a proxy at all. It should think that it has direct access. You can use a factory to create either the real object or a proxy. Listen to the full episode or you can read the full transcript below.

Transcript

The basic description says that this pattern provides access to an object through another surrogate or placeholder object. Why would you want to purposefully introduce a middleman?

If you’re buying or selling an item, your first inclination might be to avoid another person and go straight to the seller or buyer. This might work out well for you and you can get a better deal. But is that always the case? A good agent should help you more than what it costs to retain the agent. Or maybe you have something to sell and there’s a local store willing to buy the item from you today at a lower cost. You can sell the item to the store or wait until you find a direct buyer and hope to get a better price. What I’m trying to say is that in real life, going through another person or company instead of directly to your intended client or customer is sometimes very useful. And there are valid reasons why you might want to do the same thing in software.

Here are three common reasons that the proxy pattern is used:

◦ 1. The real object might be big or slow to create. Maybe this object is only used rarely in your application. Or maybe it’s always used but just not right away. You can either make the user wait, add extra complexity to your program to skip this object and come back to it later, or use a proxy. If you use a proxy, then you can let the proxy create the object when it needs to.

◦ 2. The real object might not exist on your local computer at all. Or if it does exist on your local computer, it might live in another process that’s isolated from your application. A proxy allows you to work with the object as if it’s readily available nearby. In this case, the proxy might need to convert the parameters in the method call into data that can be sent across process boundaries or across machine boundaries where it can be reconstructed back into a method call on the other end. the same thing then needs to be done with any return values. When done right, the local code makes a call to a proxy and gets back the desired results as if the proxy did all the work. This could take a lot longer than a simple method call so you’ll want to consider this when designing your application.

◦ 3. You need to do some extra work when accessing the object such as coordinating access from multiple users. There was one time when I was younger that I behaved like a poorly written proxy and ended up getting fired. I was working at a pizza parlor and answering multiple phone lines to take orders. This was the first time I had done anything like this and I answered the phone to take this lady’s order. But before I could finish, the other phone rang. I asked the lady to please hold and answered the second phone. With no other interruptions, I completed the second caller’s order and went back to the first lady. Well, the other phone rang again and I’m sure you can see where this is going. I put the first lady on hold so many times that she called back to complain. Trust me, if you’re going to write a proxy to do this sort of coordinating, do it right and you’ll get great results.

There’s often another reason cited for this pattern that I left out on purpose. I’ll explain why and give you some more guidance for this pattern right after this message from our sponsor.

( Message from Sponsor )

Most of the documentation that describes the proxy pattern actually mentions another common scenario to control access to an object. Maybe you want to verify if the calling code is actually allowed to use the object. I’m going to take a different approach here and recognize that while this may be a valid fourth use of a proxy, I’m not going to list it with the other three because I think that gives the wrong idea. Here’s what I mean. Any object responsible for security needs to be protected and reliable. Now typically, a proxy runs in an application right along with the other code. To me, this is sort of like putting the prisoners in charge of the prison. Nobody would do that, right? the strange thing is that when it comes to software, sometimes developers fail to think about their designs in real-world terms. I’ve seen lots of examples that verify a user authorization to perform some action and if the user checks out okay, then the proxy forwards the request to the real object to perform the action.

The real object relies on the proxy to perform the necessary checks. This is actually okay and can help simplify the real object. But only if the proxy is protected. If you put the proxy on some user’s computer, then it’s under that user’s full control. Now granted, most users won’t know what to do with this or how to exploit the vulnerability. But it only takes one user to figure out that all they need to do is change a little bit of code to bypass the authorization and always make the call to the real object to perform the work.

I left this common use out because I think it needs more explanation and warning or it’s likely to lead to a security vulnerability.

Implementing a proxy is fairly straightforward. Since it needs to be used in place of the real object, it needs to have the same interface as the real object. Ideally, the code using a proxy shouldn’t know that it’s using a proxy at all. It should think that it has direct access.

You’ll probably want a factory to create either the real object or the proxy. That way, your code won’t know which it’s working with. The factory can either return a real object or return a proxy that either already knows about the real object or has enough information to find or construct the real object when needed.

Episode 67 describes the decorator pattern which also needs to have the same interface just like a proxy. The difference though is that a decorator is designed to add extra behavior while a proxy is designed to forward requests to the real object and maybe do some extra work as well. But proxies, don’t add new features like a decorator. And proxies are not designed like decorators to be used in multiple levels. I mean, you wouldn’t have a proxy that refers to another proxy and so on until it finally reaches the real object. There’s just one proxy that refers to the real object.