java - ¿Son los métodos privados realmente seguros?
reflection private (7)
Al decir ''seguro'', usted está protegiendo a usted u otros desarrolladores, que están usando su API para no dañar el objeto al llamar a su método privado. Pero si realmente necesitan llamar a este método, pueden hacerlo con Reflection.
En Java, el modificador de acceso private
considera seguro ya que no es visible fuera de la clase. Entonces, el mundo exterior tampoco sabe acerca de ese método.
Pero pensé que la reflexión de Java puede usarse para romper esta regla. Considera seguir el caso:
public class ProtectedPrivacy{
private String getInfo(){
return "confidential";
}
}
Ahora de otra clase, voy a obtener información:
public class BreakPrivacy{
public static void main(String[] args) throws Exception {
ProtectedPrivacy protectedPrivacy = new ProtectedPrivacy();
Method method = protectedPrivacy.getClass().getDeclaredMethod("getInfo", null);
method.setAccessible(true);
Object result = method.invoke(protectedPrivacy);
System.out.println(result.toString());
}
}
En este momento solo pensé en un método privado seguro ya que para hacer algo como arriba debemos saber el nombre del método. Pero si la clase contiene un método privado escrito por alguien más, no tenemos visibilidad de esos.
Pero mi punto se vuelve inválido ya que debajo de la línea de código.
Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();
Ahora este method[]
contiene todas las cosas necesarias para hacer lo anterior. Mi pregunta es, ¿hay alguna manera de evitar este tipo de cosas haciendo uso de la reflexión de Java?
Cito un punto de la documentación de Java para aclarar mi pregunta.
Consejos para elegir un nivel de acceso:
Si otros programadores usan tu clase, debes asegurarte de que no puedan producirse errores por uso indebido. Los niveles de acceso pueden ayudarlo a hacer esto. Use el nivel de acceso más restrictivo que tenga sentido para un miembro en particular. Use privado a menos que tenga una buena razón para no hacerlo.
Con facilidad, viene la responsabilidad. Hay cosas que no puedes hacer y cosas que puedes hacer pero que no debes hacer.
El modificador privado se proporciona / usa como / de la manera más restringida. Los miembros que no deberían ser visibles fuera de la clase se definirán como privados. Pero esto se puede romper con la Reflexión como vemos. Pero esto no significa que no deba usar privado, o no son seguros. Se trata de usar las cosas juiciosamente o de manera constructiva (como la reflexión).
Depende de lo que quiere decir con "seguro". Si se está ejecutando con un administrador de seguridad que permite este tipo de cosas, entonces sí, puede hacer todo tipo de cosas desagradables con la reflexión. Pero luego, en ese tipo de entorno, la biblioteca probablemente solo pueda modificarse para hacer que el método sea público de todos modos.
El control de acceso es efectivamente "asesor" en un entorno como ese; de hecho, confías en que el código funcione correctamente. Si no confía en el código que está ejecutando, debe usar un administrador de seguridad más restrictivo.
La pregunta es de quién estás tratando de salvarlo . En mi opinión, ese cliente de tu código es el que está perdido aquí.
Cualquier fragmento de código (escrito por usted o por otras personas) que intente acceder a un miembro private
de la clase anterior es, en esencia, cavar su propia tumba. private
miembros private
no forman parte de la API pública y están sujetos a cambios sin previo aviso. Si un cliente consume a uno de estos miembros privados de la manera descrita anteriormente, se romperá si se actualiza a una versión más nueva de la API en la que el miembro privado fue modificado.
Los modificadores de acceso no tienen nada que ver con la seguridad. De hecho, puede y debe considerar los modificadores de acceso como el reverso de la seguridad; no es para proteger sus datos o algoritmos, sino para proteger a las personas del requisito de conocer sus datos y algoritmos. Esta es la razón por la cual el modificador predeterminado es el paquete: si están trabajando en el paquete, probablemente ya necesiten saberlo.
Junto con el conocimiento de los datos y los métodos de su código, surge la responsabilidad de saber cuándo y cómo usarlo. Usted no pone en privado su método inIt para evitar que alguien lo descubra, lo hace porque (a) no sabrá que solo lo llama después de foo y solo si bar = 3.1415 y (b) porque no les hace bien saberlo.
Los modificadores de acceso se pueden resumir en una frase simple "TMI, amigo, así que no necesitaba saber eso".
Suponiendo que confíe en el programador cliente de su API, otra forma de ver qué tan ''seguro'' es para ellos usar esas funciones particulares.
Sus funciones disponibles públicamente deben proporcionar una interfaz clara, bien documentada y que rara vez cambia en su código. Sus funciones privadas se pueden considerar un detalle de implementación y pueden cambiar con el tiempo, por lo que no es seguro usarlas directamente.
Si un programador cliente se desvía de su camino para eludir estas abstracciones, de alguna manera están declarando que saben lo que están haciendo. Más importante aún, entienden que no es compatible y puede dejar de funcionar con versiones futuras de su código.
private
no es para seguridad, es para mantener el código limpio y evitar errores. Permite a los usuarios modularizar el código (y cómo se desarrolla) sin tener que preocuparse por todos los detalles de los otros módulos
Una vez que liberas tu código, las personas pueden descubrir cómo funciona. No hay forma de "ocultar" la lógica si finalmente desea que el código se ejecute en una computadora. Incluso compilar a binario es un nivel de ofuscación.
Por lo tanto, no hay forma de que pueda configurar su API para hacer cosas especiales que no desea que otros puedan llamar. En el caso de una API web, podría poner los métodos que desea controlar en el lado del servidor.