사적인 방법은 정말 안전합니까?


92

Java에서 private액세스 수정자는 클래스 외부에서 볼 수 없기 때문에 안전한 것으로 간주합니다. 그러면 외부 세계도 그 방법에 대해 알지 못합니다.

하지만 Java 리플렉션이이 규칙을 깨는 데 사용할 수 있다고 생각했습니다. 다음 경우를 고려하십시오.

public class ProtectedPrivacy{

  private String getInfo(){
     return "confidential"; 
  }

}  

이제 다른 클래스에서 정보를 얻을 것입니다.

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());
   }
} 

지금은 위와 같은 일을하기 위해서는 메소드 이름을 알아야하므로 여전히 private 메소드가 안전하다고 생각했습니다. 그러나 다른 누군가가 작성한 private 메서드를 포함하는 클래스는 가시성이 없습니다.

그러나 코드 줄 아래부터 내 요점이 무효화됩니다.

Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();

이제 여기 method[]에는 위의 작업에 필요한 모든 것이 포함됩니다. 제 질문은 Java 리플렉션을 사용하여 이러한 종류의 일을 피할 수있는 방법이 있습니까?

내 질문을 명확히하기 위해 Java Documentation 에서 몇 가지 요점을 인용했습니다 .

액세스 수준 선택에 대한 팁 :

다른 프로그래머가 클래스를 사용하는 경우 오용으로 인한 오류가 발생하지 않도록해야합니다. 액세스 수준은이를 수행하는 데 도움이 될 수 있습니다. 특정 구성원에게 적합한 가장 제한적인 액세스 수준을 사용합니다. 정당한 이유가없는 한 비공개로 사용하세요.


1
난 독자를 사용하면 getDeclaredMethods쓰레기처럼 보이는 이름이 반환 되기 때문에 도움이 될 수 있습니다 .
dasblinkenlight 2013

213
개인, 보호 된 공공 등은 보안을위한 것이 아니라 사람들이 실수를 저 지르지 않도록하는 것입니다. 보안 조치로 사용하지 마십시오
Richard Tingle 2013

20
어쨌든 Java 코드는 디 컴파일 가능합니다. '공격자'는 자바 디 컴파일러를 다운로드하고 코드를 읽거나 'private'를 'public'으로 변경할 수 있습니다.
11,684

7
@RichardTingle이 코멘트 한 내용을 자세히 설명합니다 (+1 btw). 보안과 안전 사이에는 크고 중요한 차이가 있습니다. 후자가 액세스 수정 자로 완화 된 문제인 경우 실수로
user

3
이 모든 것은 파이썬과 같이 접근 수정자가 존재하지 않는 프로그래머에게 매우 분명합니다. 이러한 언어에서 private / public은 이름의 규칙으로 구분됩니다 (파이썬에서는 단일 밑줄로 시작하는 모든 것은 private으로 간주되어야합니다). 이것은 꽤 "개인"으로 뭔가를 마킹 않음을 취소하게 하지 보안을 추가 할 수 있지만이 사람들이 무슨 말을의 간단한 방법 해야 당신의 API를 사용합니다. "외부"의 도움 없이는 규칙을 따르기 쉽기 때문에 컴파일러가이 일을 확인하는 것이 전혀 도움이되지 않는다고 의심합니다.
Bakuriu 2013

답변:


95

"안전하다"는 의미에 따라 다릅니다. 이런 종류의 일을 허용하는 보안 관리자와 함께 실행하는 경우 예, 모든 종류의 불쾌한 일을 반성 할 수 있습니다. 그러나 그런 종류의 환경에서 라이브러리는 어쨌든 메소드를 공개하도록 수정 될 수 있습니다.

액세스 제어는 이와 같은 환경에서 효과적으로 "자문"입니다. 코드가 멋지게 재생되는 것을 효과적으로 신뢰하고 있습니다. 실행중인 코드를 신뢰할 수 없다면 더 제한적인 보안 관리자를 사용해야합니다.


3
Tangential, 알아요.하지만 이런 의미에서 더 제한적인 관리자가 무엇인지에 대해 조금 더 자세히 설명해 주시겠습니까?
회색

12
@Gray : 기본적으로 관련 호출에서 예외를 발생시키는 SecurityManager 의 인스턴스입니다 check*.
Jon Skeet 2013

40

액세스 수정자는 보안과 관련이 없습니다. 실제로 액세스 수정자를 보안의 역방향으로 볼 수 있습니다. 이는 데이터 나 알고리즘을 보호하는 것이 아니라 데이터와 알고리즘에 대해 알아야하는 요구 사항으로부터 사람들을 보호하는 것입니다. 이것이 기본 수정자가 package 인 이유입니다. 패키지에서 작업중인 경우 이미 알아야 할 것입니다.

데이터 및 코드 방법에 대한 지식과 함께 사용시기와 방법을 알 책임이 있습니다. 누군가가 그것에 대해 알아내는 것을 막기 위해 inIt 메서드에 비공개를 두지 않습니다. (a) foo 다음에 호출하고 bar = 3.1415 및 (b) 인 경우에만 호출한다는 것을 알지 못하기 때문입니다. 그들이 그것에 대해 아는 것이 좋지 않기 때문입니다.

액세스 modifers이 간단한 문구로 요약 할 수있다 "TMI, 친구, 내가 그렇게 알 필요하지 않았다."


3
좋은 대답이지만 TMI가 너무 많은 정보를 의미한다는 것을 알기 위해 Google을 검색해야했습니다. 나는 계곡에서 더 많은 시간을 보낼 필요가 있다고 생각한다 :-)
mikelong

7

'안전하다'는 말은 개인 메서드를 호출하여 개체에 해를 끼치 지 않기 위해 API를 사용하는 귀하 또는 다른 개발자를 보호하는 것입니다. 그러나 당신이나 그들이 정말로이 메서드를 호출해야한다면, 리플렉션으로 할 수 있습니다.


6

문제는 누구 로부터 저장 하려고 하는가입니다. 내 생각에, 당신의 코드의 그러한 클라이언트는 여기서 손실을 입는 것이다.

private위 클래스 의 구성원에 액세스하려고 시도하는 코드 (귀하 또는 다른 사람이 작성한) 는 본질적으로 자체 무덤을 파고 있습니다. private회원은 공개 API 의 일부를 만들지 않으며 예고없이 변경 될 수 있습니다. 클라이언트가 위와 같은 방식으로 이러한 개인 구성원 중 하나를 사용하는 경우 개인 구성원이 수정 된 API의 최신 버전으로 업그레이드하면 중단됩니다.


5

시설에는 책임이 따릅니다. 이 일이 당신의있다 없다 할, 당신이 일 할 수 있지만 하지 말아야 할.

Private modifier는 가장 제한된 방식으로 제공 / 사용됩니다. 클래스 외부에서 보이지 않아야하는 멤버는 비공개로 정의됩니다. 그러나 이것은 우리가 볼 수 있듯이 Reflection으로 깨질 수 있습니다. 그러나 이것은 당신이 개인적으로 사용해서는 안된다는 것을 의미하지는 않습니다. 그것은 당신이 사물을 현명하게 또는 건설적인 방식으로 (반성처럼) 사용하는 것에 관한 것입니다.


5

API의 클라이언트 프로그래머를 신뢰한다고 가정 할 때 다른 방법은 특정 기능을 사용하는 것이 얼마나 '안전'한지입니다.

공개적으로 사용 가능한 함수는 코드에 명확하고 잘 문서화되고 거의 변경되지 않는 인터페이스를 제공해야합니다. 개인 기능은 구현 세부 사항으로 간주 될 수 있으며 시간이 지남에 따라 변경 될 수 있으므로 직접 사용하는 것이 안전하지 않습니다.

클라이언트 프로그래머가 이러한 추상화를 회피하기 위해 자신의 방식을 벗어나면 자신이 무엇을하고 있는지 알고 있다고 선언하는 것입니다. 더 중요한 것은 지원되지 않으며 향후 버전의 코드 작업이 중단 될 수 있음을 이해하고 있다는 것입니다.


5

private보안을위한 것이 아니라 코드를 깨끗하게 유지하고 실수를 방지하는 것입니다. 이를 통해 사용자 는 다른 모듈의 모든 세부 사항에 대해 걱정할 필요없이 코드 (및 개발 방법)를 모듈화 할 수 있습니다.

코드를 공개하면 사람들이 코드가 어떻게 작동하는지 알아낼 수 있습니다. 결국 컴퓨터에서 코드를 실행하려는 경우 논리를 "숨길"방법이 없습니다. 바이너리로 컴파일하는 것조차 난독 화 수준입니다.

따라서 다른 사람이 호출하지 못하도록하는 특별한 작업을 수행하도록 API를 설정할 수있는 방법이 없습니다. 웹 API의 경우 제어 할 메서드를 서버 측에 둘 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.