views:

147

answers:

2

If you implement an interface in Java, there is nothing to prevent the caller from looking at what concrete implementation you have supplied, casting to that class and calling methods that are not in the interface. I believe this is called "malicious downcasting".

A way to prevent this is to create a wrapper that only has the interface's methods and does not expose the implementation instance to which it delegates. Short of reflection to private variables you should be safe.

Is there a way to automatically create these kind of wrappers (at run-time, not using a code creation wizard in the IDE, because that still creates a source file that needs to be maintained) ?

+8  A: 

Another way to protect against this is to use a factory class, and have the implementation be a private inner class of the factory. Only the factory can see it and it will return only the interface type so there is no concrete implementation to cast against.

James Black
I suppose along the same lines, one could also use a package protected class for one's concrete implementation.
Thilo
The problem with a package protected class is what prevents someone from adding to your package and then seeing what is going on?
James Black
@James: That would require permission to use a custom classloader, wouldn't it? And if your SecurityManager doesn't prohibit _that_, then you've lost already.
Chris Jester-Young
(Hint: private inner/nested classes are still, in Java's permissions system, package-private; reflection can be used to get at the concrete type, if known, and if the calling class is in the right package.)
Chris Jester-Young
By using AOP you can get past most protections, even if you shouldn't have access to classes. I can put an around on a call to the concrete class methods and do whatever I want.
James Black
@James: Sealing your package (a JAR option) can suitably prevent someone from "adding" to your package using classes located outside of your JAR. Signing your JAR and suitable O/S security can protect your JAR from being altered or messed with. But in the end nothing can stop a malicious user from repackaging your classes if they have the necessary authority on the running system.
Software Monkey
+7  A: 

I like James Black's answer, but for diversity, I'll post an alternative approach.

You can use java.lang.reflect.Proxy to do this. See this post for some code I wrote (for a different question) that uses Proxy; you can use similar code, if you strip out the synchronization stuff.

Chris Jester-Young