정보가 협약 이상의 것을 숨기고 있습니까?


20

Java, C # 및 기타 강력한 형식의 정적으로 확인 된 언어에서 다음과 같은 코드를 작성하는 데 사용됩니다.

public void m1() { ... }
protected void m2() { ... }
private void m2() { ... }
void m2() { ... }

동적으로 확인 된 일부 언어는 지정된 클래스 구성원의 "개인"수준을 표현하기위한 키워드를 제공하지 않으며 대신 코딩 규칙에 의존합니다. 예를 들어 Python은 개인 멤버 앞에 밑줄을 붙입니다.

_m(self): pass

동적으로 확인 된 언어로 이러한 키워드를 제공하면 런타임에만 확인되기 때문에 거의 사용하지 않을 것이라고 주장 할 수 있습니다.

그러나 이러한 키워드를 정적으로 확인 된 언어로 제공해야 할 이유는 없습니다. protected성가신 것과 산만 한 것과 같은 다소 장황한 키워드로 코드를 작성 해야하는 요구 사항을 발견했습니다 . 지금까지 이러한 키워드로 인한 컴파일러 오류로 인해 버그에서 벗어날 수 없었습니다. 반대로, 실수로 protected도서관을 이용할 수 없는 상황에 처해있었습니다 .

이것을 염두에두고 내 질문은 다음과 같습니다.

클래스의 공식 인터페이스의 일부를 정의하는 데 사용되는 프로그래머 간 규칙 이상의 정보가 숨겨져 있습니까?

클래스의 비밀 상태를 공격으로부터 보호하는 데 사용할 수 있습니까? 리플렉션이이 메커니즘을 무시할 수 있습니까? 컴파일러가 정보 숨기기 를 시행 하는 것이 무엇이 가치가 있습니까?


10
죄송합니다, Eric Lippert가 휴가 중입니다 :)
Benjol

귀하의 질문은 이해하기 조금 어렵습니다. 기본적으로 누군가 외부에서 개인 회원에게 액세스 할 수 있는지 묻고 있습니까?
Morgan Herlocker


@ ironcode : 나는 어떻게 든 대답에서 충분히 명확하게 표현하지 못한다고 말할 수 있습니다. 구체적으로 이해하기 어려운 점을 알 수 있습니까? 나는 명확히하려고 노력할 것이다.
blubb

2
"컴파일 타임에 정보를 제공 한 다음 런타임에만 정보를 확인하는 것은 말도 안됩니다"-정말로? 현재 .NET 프레임 워크의 중요한 부분이 기반으로하기 때문에 선택적으로 정적 입력을 옵트 인 또는 옵트 아웃하기 때문에 Microsoft에 더 잘 알립니다. 나는 이것이 실제로 당신이 의미하는 것이라고 생각하지 않습니다. 이 질문은 "정적"대 "동적"검사에 대해 반복적으로 이야기하지만 유형 시스템의 특성입니다. 여기서 실제로 문제가되는 것은 컴파일 타임런타임 바인딩 입니다.
Aaronaught

답변:


4

Java 인증을 연구 중이며 액세스 수정자를 관리하는 방법과 관련이 있습니다. 그리고 그들은 말이되고 올바르게 사용되어야합니다.

나는 파이썬으로 일했고, 학습 과정에서 파이썬에서 그 일을하는 사람들은 그것이 무엇을 의미하고 적용하는 방법을 알아야하기 때문에 그 규칙이 있다는 것을 들었습니다. 즉, _m(self): pass밑줄로 해당 필드를 어지럽히 지 말라고 경고합니다. 그러나 모든 사람들이 그 협약을 따를 것입니까? 나는 자바 스크립트로 작업하고 말하지 않아야 합니다. 때로는 문제를 확인해야하며 그 이유는 그 사람이하지 말아야 할 일을하고 있었기 때문입니다.

파이썬 주요 밑줄에 관한 토론을 읽으십시오.

클래스의 공식 인터페이스의 일부를 정의하는 데 사용되는 프로그래머 간 규칙 이상의 정보가 숨겨져 있습니까?

내가 한 말에서 그렇습니다.

클래스의 비밀 상태를 공격으로부터 보호하는 데 사용할 수 있습니까? 리플렉션이이 메커니즘을 무시할 수 있습니까? 컴파일러에 의해 시행되는보다 공식적인 메커니즘에 의해 제공되는 다른 이점이 있습니까?

예. 클래스의 비밀 상태를 보호하는 데 사용할 수 있으며 그 용도뿐만 아니라 사용자가 객체의 상태와 같아야하는 행동으로 행동을 변경하기 위해 사용자가 객체 상태를 엉망으로 만드는 것을 방지해야합니다 일하고 있었다. 개발자는 자신의 행동을 방해하지 않는 방식으로 계획하고 생각하고 클래스를 디자인해야합니다. 그리고 좋은 친구 인 컴파일러는 액세스 정책을 시행하도록 설계 한 방식으로 코드를 유지하는 데 도움이됩니다.

편집 예, 반영, 의견 확인

마지막 질문은 흥미로운 질문이며 이에 관한 답변을 기꺼이 읽겠습니다.


3
반사는 일반적으로 액세스 보호를 우회 할 수 있습니다. Java 및 C #의 경우 둘 다 개인 데이터에 액세스 할 수 있습니다.
Mark H

감사! 여기에 대한 답변 : stackoverflow.com/questions/1565734/… 설명하십시오!
wleao

1
자바 스크립트 문화는 파이썬 문화와 매우 다릅니다. 파이썬에는 pep-08이 있으며 거의 ​​모든 파이썬 개발자는 이러한 규칙을 따릅니다. PEP-08 위반은 종종 버그로 간주됩니다. 따라서 자바 스크립트 / PHP / 펄 / 루비 경험은이 측면에서 파이썬 경험으로 거의 변환되지 않는다고 생각합니다. _private는 파이썬에서 매우 잘 작동합니다.
Mike Korobov

1
일부 (전부는 아님) 프로그래밍 언어에서는 정보 숨기기를 사용하여 악의적 인 코드로부터 보호 할 수 있습니다. 적대적 사용자로부터 보호하기 위해 정보 숨기기를 사용할 수 없습니다.
Brian

2
@ PEP-08 위반이 종종 "버그로 간주"되고 파이썬 개발자가 컨벤션을 따르지 않는 꿈을 꾸지 않는다면, 언어에 의해 시행 될 수 있습니다! 언어가 자동으로 할 수있을 때 왜 정신적 인 일을 하는가?
Andres F.

27

"private"액세스 지정자는 처음 볼 때 생성되는 컴파일러 오류에 관한 것이 아닙니다. 현실에서는 그것이 관하여 방지 여전히 변경 될 수 있습니다 뭔가를 액세스를 할 때 전용 멤버 변화를 잡고 클래스의 구현입니다.

다시 말해, 여전히 작동중인 상태에서 사용할 수 없도록 하면 더 이상 작동하지 않을 때 실수로 계속 사용할 수 없게됩니다.

접두사 협약 아래에 Delnan이 언급 한 바와 같이 협약을 준수하고 올바르게 이해하는 한 변경 될 수있는 구성원의 우발적 인 사용은 권장하지 않습니다. 악의적 인 (또는 무식한) 사용자의 경우 가능한 모든 결과로 해당 구성원에 액세스하는 것을 막지 않습니다. 액세스 지정자를 기본적으로 지원하는 언어에서는 무지 (컴파일러 오류)가 발생하지 않으며 악의적 인 경우 (엄격한 구성이 개인 구성원에게 도달) 아픈 것처럼 보입니다.

"보호 된"액세스 지정자는 다른 이야기입니다. 이것을 단순히 "공개적이지 않은"또는 "비공개 적"이라고 생각하지 마십시오. "보호됨" 은 보호 된 멤버가 포함 된 클래스에서 파생 될 때 해당 기능을 사용 하려고 함을 의미합니다 . 보호 된 멤버는 기존 클래스 자체를 변경하지 않고 기존 클래스 위에 기능을 추가하는 데 사용할 "확장 인터페이스"의 일부입니다.

짧은 요약 :

  • 공개 : 클래스의 인스턴스에서 안전하게 사용하십시오. 클래스의 목적은 변경되지 않습니다.
  • protected : 클래스를 확장 (파생) 할 때 사용-구현이 크게 변경되면 변경 될 수 있습니다.
  • 개인 : 만지지 마십시오! 예상되는 인터페이스를 더 잘 구현하기 위해 마음대로 변경할 수 있습니다.

3
더 중요한 것은, "구현 세부 사항, 변경 될 수 있음"에 대한 관행 을 강제하지 않는 (쉽게 인식 할 수있는, 예를 들어 밑줄이있는 경우) 개인 구성원이 우발적으로 사용하는 것을 피합니다. 예를 들어, 파이썬에서 제정신 프로그래머가 외부에서 비공개 멤버를 사용하여 코드를 작성하는 유일한 시점 (그리고 찌그러진 경우)은 거의 피할 수 없을 때이며, 자신이하는 일을 정확히 알고 있으며 향후 버전에서 잠재적 인 파손을 받아들입니다. . 즉, 예를 들어 Java 프로그래머가 리플렉션을 사용하는 상황입니다.

3
@Simon Stelling-아니요, 비공개로 만든 클래스의 원래 구현자는 "이 기능을 사용하지 마십시오. 앞으로 어떤 동작이 변경 될 수 있습니다"라고 말합니다. 예를 들어, 먼저 두 점 사이의 거리를 포함하는 클래스의 전용 멤버 변수에는 나중에 성능상의 이유로 두 점 사이의 거리가 제곱 될 수 있습니다. 예전 행동에 의존했던 것은 조용히 깰 것입니다.
Joris Timmermans

1
@MadKeithV : 그렇다면 같은 단어를 의미하는 규칙과 다른 언어 수준 키워드는 "만지지 않기 때문에 ..."라는 말은 어떻게 다른가요? 컴파일러 만이 그것을 시행하지만, 우리는 예전의 정적 대 동적 토론으로 돌아갑니다.

7
@Simon Stelling (및 Delnan)- "엔진 리미터가 속도 제한 표지판과 어떻게 다른지"를 묻는 것과 같습니다.
Joris Timmermans

1
나는 그 차이를 잘 알고 있으며 그것이 없다고 말한 적이 없다. 나는 당신의 대답과 대부분의 후속 의견은 단지 규칙 이나 언어 수준 키워드로 만들 수있는 구성원과 방법에 대한 주석의 종류를 설명 하고 실제 차이 (언어 수준 시행의 존재)를 그대로 둡니다. 독자가 유추했습니다.

11

다른 사람이 사용할 코드를 작성하는 경우 정보 숨기기로 인터페이스를 훨씬 쉽게 이해할 수 있습니다. "다른 사람"은 팀의 다른 개발자, 상업적으로 작성한 API를 사용하는 개발자 또는 "당당한 일이 어떻게 작동하는지 기억할 수없는 미래의 자기 자신"일 수도 있습니다. 40 개가있는 것보다 4 개의 메서드 만 사용할 수있는 클래스로 작업하는 것이 훨씬 쉽습니다.


2
나는 완전히 동의하지만 이것은 내 질문에 대답하지 않습니다. 내가 사용 여부 _member또는 private member내 수업은 다른 프로그래머가 자신 만 볼 것을 이해 한대로, 무시할 public또는 비 접두어 회원.
blubb

6
예, 그러나 동적 언어로 작성된 클래스의 공개 문서는 36 가지 개인 부분을 (기본적으로는 아닙니다) 던지지 않습니다.

3
@Simon "단순한 협약"이라는 말은 실제 이점이 있기 때문에 오해의 소지가 있습니다. "컨벤션"은 다음 줄의 중괄호와 같은 것입니다. 이점이있는 규칙은 의미있는 이름을 사용하는 것과 비슷합니다. 비공개로 설정하면 누군가가 "비밀 방법"을 보지 못하게됩니까? 그들이 결정되면 아닙니다.
Morgan Herlocker

1
@ Simon- 또한 사용하기에 안전한 메소드 만 노출하면 클래스를 사용할 때 사용자가 무언가를 깨뜨리지 않을 가능성이 높아집니다. 수천 번 호출하면 웹 서버가 충돌 할 수있는 방법이 쉽게 있습니다. API 소비자가 그렇게 할 수 있기를 원하지 않습니다. 추상화는 단순한 컨벤션 그 이상입니다.
Morgan Herlocker

4

배경에 대해서는 클래스 불변 에 대해 읽는 것으로 시작하는 것이 좋습니다 .

변하지 않는 것은, 긴 이야기를 짧게하기 위해, 클래스의 수명 동안 계속 유지되어야하는 클래스의 상태에 대한 가정 이다.

정말 간단한 C # 예제를 사용하십시오.

public class EmailAlert
{
    private readonly List<string> addresses = new List<string>();

    public void AddRecipient(string address)
    {
        if (!string.IsNullOrEmpty(address))
            addresses.Add(address);
    }

    public void Send(string message)
    {
        foreach (string address in addresses)
            SendTo(address, message);
    }

    // Details of SendTo not shown
}

무슨 일이야?

  • 멤버 addresses는 클래스 생성시 초기화됩니다.
  • 비공개이므로 외부에서 만질 수 없습니다.
  • 우리는 또한 그것을 만들었 readonly으므로 내부 에서 아무것도 건설 후에 만질 수 없습니다 (항상 정확하거나 필요한 것은 아니지만 여기에서는 유용합니다).
  • 따라서이 Send방법 addresses은 절대로 가정 하지 않을 수 있습니다 null. 값을 변경할 수있는 방법없으므로 검사를 수행 할 필요가 없습니다 .

다른 클래스가 addresses필드 에 쓰도록 허용 된 경우 (예 : 인 경우 public)이 가정은 더 이상 유효하지 않습니다. 해당 필드에 의존하는 클래스의 다른 모든 단일 메소드는 명시적인 널 검사를 시작 하거나 프로그램 충돌의 위험이 있습니다.

그렇습니다. "컨벤션"이상입니다. 클래스 멤버의 모든 액세스 수정자는 집합 적으로 해당 상태를 언제 어떻게 변경할 수 있는지에 대한 일련의 가정을 형성합니다. 이러한 가정은 프로그래머가 프로그램의 전체 상태를 동시에 추론 할 필요가 없도록 종속 및 상호 의존적 멤버 및 클래스에 통합됩니다. 가정의 능력은 소프트웨어의 복잡성을 관리하는 데 중요한 요소입니다.

이 다른 질문들에 :

클래스의 비밀 상태를 공격으로부터 보호하는 데 사용할 수 있습니까?

예, 아니오 대부분의 코드와 마찬가지로 보안 코드는 특정 불변에 의존합니다. 액세스 수정자는 신뢰할 수있는 발신자에게 푯말로 도움 이되지 않습니다. 악성 코드는 신경 쓰지 않지만 악성 코드는 컴파일러를 거치지 않아도됩니다.

리플렉션이이 메커니즘을 무시할 수 있습니까?

물론 가능합니다. 그러나 리플렉션을 사용하려면 호출 코드에 해당 권한 / 신뢰 수준이 있어야합니다. 완전한 신뢰 및 / 또는 관리 권한으로 악성 코드를 실행하고 있다면 이미 그 전투에서 패배 한 것입니다.

컴파일러가 정보 숨기기를 시행하는 것이 무엇이 가치가 있습니까?

컴파일러는 이미 수행 을 적용합니다. .NET, Java 및 기타 환경에서 런타임도 마찬가지입니다. 메소드가 개인용 인 경우 메소드를 호출하는 데 사용되는 opcode는 성공하지 못합니다. 이러한 제한을 해결하는 유일한 방법은 신뢰할 수있는 / 높은 코드가 필요하며, 높은 코드는 항상 프로그램의 메모리에 직접 쓸 수 있습니다. 사용자 지정 운영 체제 없이도 시행 할 있는 만큼 시행됩니다 .


1
@Simon : 여기서 "무지"를 명확히해야합니다. 메소드 앞에 접두어를 붙이면 _계약이 적용되지만 강제하지는 않습니다. 계약을 무시 하기 어려울 수 있지만 , 특히 성찰과 같은 지루하고 종종 제한적인 방법과 비교할 때 계약 을 어기 는 것은 어렵지 않습니다. 컨벤션에 따르면 " 이를 중단 해서는 안된다 "고합니다. 액세스 수정자는 " 이를 깨뜨릴 수 없습니다 "라고 말합니다 . 나는 하나의 접근법이 다른 접근법 보다 낫다고 말하려고 하지는 않습니다 -그들은 당신의 철학에 따라 훌륭하지만 그럼에도 불구하고 매우 다른 접근법입니다.
Aaronaught

2
유추는 어떻습니까 : A private/ protectedaccess modifier는 콘돔과 같습니다. 당신이 그것을 사용할 필요는 없지만 당신이하지 않을 경우 타이밍과 파트너에 대해 확신하는 것이 좋습니다. 악의적 인 행동을 막을 수는 없으며 매번 작동하지 않을 수도 있지만 부주의로 인한 위험을 확실히 낮추고 "조심하십시오"라고 말하는 것보다 훨씬 더 효과적입니다. 아, 그리고 당신은 그것을 가지고 있지만 그것을 사용하지 않으면 나에게 동정심을 기대하지 마십시오.
Aaronaught

3

정보 숨기기는 단순한 컨벤션 그 이상입니다. 그것을 둘러 보려고하면 실제로 많은 경우 클래스의 기능을 손상시킬 수 있습니다. 예를 들어, private변수에 값을 저장 하고 같은 시간 protected또는 public속성을 사용하여 값을 노출 하고 게터에서 null을 확인하고 필요한 초기화 (예 : 게으른 로딩)를 수행하는 것이 일반적입니다. 아니면에 저장 뭔가 private변수는 속성을 사용하여 노출하고, 값이 변경 불 경우 세터에, 확인 PropertyChanging/ PropertyChanged이벤트. 그러나 내부 구현을 보지 않으면 뒤에서 일어나는 모든 일을 결코 알 수 없습니다.


3

정보 숨기기는 하향식 디자인 철학에서 발전했습니다. 파이썬은 상향식 언어라고합니다 .

정보 숨기기는 Java, C ++ 및 C #의 클래스 수준에서 잘 적용되므로 실제로이 수준의 규칙은 아닙니다. 공용 인터페이스와 숨겨진 (개인) 세부 정보를 사용하여 클래스를 "블랙 박스"로 만드는 것은 매우 쉽습니다.

알다시피, 파이썬에서는 모든 것이 보이기 때문에 숨겨져있는 것을 사용하지 않는 관례를 따르는 것은 프로그래머에게 달려 있습니다.

Java, C ++ 또는 C #을 사용하더라도 어느 시점에서 정보 숨기기 규칙이됩니다. 보다 복잡한 소프트웨어 아키텍처와 관련된 최고 수준의 추상화에는 액세스 제어가 없습니다. 예를 들어, Java에서는 ".internal"을 사용할 수 있습니다 . 패키지 이름. 패키지 접근성만으로 이러한 종류의 정보 숨기기를 시행하기가 쉽지 않기 때문에 이것은 순전히 명명 규칙입니다.

공식적으로 액세스를 정의하려고 노력하는 언어 중 하나는 에펠입니다. 이 기사에서는 Java와 같은 언어의 다른 정보 숨기기 취약점을 지적합니다.

배경 : 정보 숨기기는 1971 년 David Parnas에 의해 제안되었습니다 . 그는이 기사에서 다른 모듈에 대한 정보를 사용하면 "시스템 구조의 연결성을 비참하게 증가시킬 수있다"고 지적했다. 이 아이디어에 따르면 정보 숨기기가 부족하면 유지 관리하기 어려운 밀접하게 연결된 시스템으로 이어질 수 있습니다. 그는 다음과 같이 계속합니다.

프로그래머가 의도하지 않은 정보 사용에 의해 프로그래밍을 시작하기 전에 설계자가 명시 적으로 시스템의 구조를 결정하기를 원합니다.


1
"프로그래머의 정보 사용"이라는 인용문은 +1입니다 (끝에 여분의 쉼표가 있더라도).
jmoreno

2

루비와 PHP는 런타임에이를 적용합니다.

정보 숨기기의 포인트는 실제로 정보를 보여주는 것입니다. 내부 세부 사항을 "숨김"으로써 목적은 외부 관점에서 명확 해집니다. 이것을 받아들이는 언어가 있습니다. Java에서 액세스는 기본적으로 내부 패키지로, haXe는 보호됩니다. 공개적으로 공개하여 공개합니다.

이것의 요점은 매우 일관된 인터페이스 만 노출하여 클래스를 사용하기 쉽게 만드는 것입니다. 당신은 나머지 사람들을 보호하기를 원하므로 영리한 사람이 와서 내부 상태를 엉망으로 만들어서 클래스가 원하는 것을하도록 속이십시오.

또한 액세스 수정자가 런타임에 시행되면이 사용하여 특정 수준의 보안을 시행 할 있지만 이것이 특히 좋은 해결책이라고 생각하지 않습니다.


1
라이브러리를 작업중인 회사와 같은 회사에서 사용중인 경우주의를 기울여야합니다. 그의 앱이 충돌하면 문제를 해결하는 데 어려움이 있습니다.
wleao

1
안전 벨트를 착용했을 때 안전 벨트를 착용하는 이유는 무엇입니까? 나는 모든 정보를 이용할 수 있다면 컴파일러가 그것을 강제 하지 않는 이유가 있는지 묻고 질문 한다. 안전 벨트를 착용 할 가치가 있는지 알아 내기 위해 충돌 사고가 발생할 때까지 기다리지 않습니다.
Mark H

1
@Simon : 사람들이 사용하기를 원하지 않는 것들로 인터페이스를 복잡하게 만드는 이유는 무엇입니까? 나는 C ++이 모든 멤버가 헤더 파일의 클래스 정의에 있어야한다는 것을 싫어합니다 (이유를 이해합니다). 인터페이스는 다른 사람들을위한 것이며 사용할 수없는 것들로 가득 차서는 안됩니다.
phkahler

1
@phkahler : 인터페이스에서 pydoc제거합니다 _prefixedMembers. 복잡한 인터페이스는 컴파일러가 확인한 키워드를 선택하는 것과 아무 관련이 없습니다.
blubb

2

Acces 수정자는 컨벤션으로는 불가능한 작업을 수행 할 수 있습니다.

예를 들어 Java에서는 리플렉션을 사용하지 않으면 개인 멤버 / 필드에 액세스 할 수 없습니다.

따라서 플러그인에 대한 인터페이스를 작성하고 리플렉션을 통해 개인 필드를 수정하고 보안 관리자를 설정하는 권한을 올바르게 거부하면 누군가가 구현 한 함수에 일부 개체를 보낼 수 있으며 개인 필드에 액세스 할 수 없다는 것을 알 수 있습니다.

물론이 문제를 극복 할 수있는 몇 가지 보안 버그가있을 수 있지만 철학적으로 중요하지는 않지만 실제로는 중요합니다.

사용자가 자신의 환경에서 내 인터페이스를 실행하면 제어 권한이 있으므로 액세스 수정자를 피할 수 있습니다.


2

이 키워드로 인한 컴파일러 오류로 인해 버그에서 벗어날 수 없었습니다.

라이브러리 작성자가 구현에서 유지 관리 할 부분을 결정할 수 있도록 버그에서 응용 프로그램 작성자를 저장하는 것은 그리 중요하지 않습니다.

도서관이 있다면

class C {
  public void foo() { ... }

  private void fooHelper() { /* lots of complex code */ }
}

foo구현 을 대체 fooHelper하고 급진적 인 방식으로 변경 하고 싶을 수도 있습니다 . fooHelper내 문서의 모든 경고에도 불구하고 많은 사람들이 사용하기로 결정한 경우에는 그렇게 할 수 없습니다.

private라이브러리 작성자 private는 몇 년 동안 내부 세부 정보를 유지해야한다는 두려움없이 라이브러리를 관리 가능한 크기의 메서드 (및 도우미 클래스) 로 나눌 수 있습니다.


컴파일러가 정보 숨기기를 시행하는 것이 무엇이 가치가 있습니까?

참고로 Java private에서는 컴파일러가 아니라 Java 바이트 코드 검증기에 의해 시행됩니다 .


리플렉션이이 메커니즘을 무시할 수 있습니까? 컴파일러가 정보 숨기기를 시행하는 것이 무엇이 가치가 있습니까?

Java에서는 리플렉션 만이이 메커니즘을 무시할 수 있습니다. privateJava 에는 두 가지 종류가 있습니다 . 이것의 종류는 private하나의 외부 클래스 private가 바이트 코드 검증기에 의해 확인되는 다른 외부 클래스의 멤버에 액세스하지 못하지만 private내부 클래스가 패키지 전용 합성 접근 자 메소드를 통해 사용합니다

 public class C {
   private int i = 42;

   public class B {
     public void incr() { ++i; }
   }
 }

class B(실제로 이름이 지정된 C$B)는을 사용 하기 때문에 i컴파일러 는 바이트 코드 검증기를 통과하는 방식 B으로 액세스 할 수있는 합성 액세서 메소드를 작성합니다 C.i. 불행히도에서 ClassLoader클래스를 만들 수 있기 때문에 jar 파일이 봉인되지 않은 경우 패키지 에서 새 클래스를 만들어 내부 클래스에 노출 된 개인을 byte[]얻는 것이 매우 간단합니다 .CCC

적절한 private시행을 위해서는 클래스 로더, 바이트 코드 검증기 및 개인에 대한 반사 액세스를 막을 수있는 보안 정책 간의 조정이 필요합니다.


클래스의 비밀 상태를 공격으로부터 보호하는 데 사용할 수 있습니까?

예. "보안 분해"는 프로그래머가 각 모듈의 보안 속성을 유지하면서 협력 할 수있을 때 가능합니다. 다른 코드 모듈의 작성자가 내 모듈의 보안 속성을 위반하지 않도록 신뢰할 필요는 없습니다.

Joe-E 와 같은 객체 기능 언어 는 정보 숨기기 및 기타 방법을 사용하여 안전한 분해가 가능합니다.

Joe-E는 객체 기능 분야에 따라 안전한 프로그래밍을 지원하도록 설계된 Java 프로그래밍 언어의 하위 집합입니다. Joe-E는 보안 시스템의 구축을 용이하게하고 Joe-E에 내장 된 시스템의 보안 검토를 용이하게하기위한 것입니다.

이 페이지에서 링크 된 논문은 private시행이 어떻게 안전한 분해를 가능하게 하는지를 보여줍니다 .

안전한 캡슐화 제공

그림 1. 추가 전용 로깅 기능

public final class Log {
  private final StringBuilder content;
  public Log() {
    content = new StringBuilder();
  }
  public void write(String s) {
    content.append(s);
  }
}

추가 전용 로그 기능을 구축하는 방법을 보여주는 그림 1을 고려하십시오. 프로그램의 나머지 부분이 Joe-E로 작성된 경우, 코드 검토자는 로그 항목 만 추가 할 수 있으며 수정하거나 제거 할 수 없음을 확신 할 수 있습니다. 이 검토는 Log 클래스 검사 만 필요하고 다른 코드를 검토 할 필요가 없기 때문에 실용적 입니다. 따라서이 특성을 확인하려면 로깅 코드에 대한 로컬 추론 만 필요합니다.


1

정보 숨기기는 좋은 소프트웨어 디자인의 주요 관심사 중 하나입니다. 70 년대 후반부터 Dave Parnas의 논문을 확인하십시오. 기본적으로 모듈의 내부 상태가 일관성을 보장 할 수 없으면 해당 동작에 대한 어떠한 것도 보증 할 수 없습니다. 내부 상태를 보장 할 수있는 유일한 방법은 개인 상태를 유지하고 사용자가 제공 한 수단으로 만 변경할 수 있도록하는 것입니다.


1

언어의 일부를 보호함으로써 합리적인 확신을 얻을 수 있습니다.

변수를 비공개로 설정하면 해당 클래스 내의 코드 또는 해당 클래스의 명시 적으로 선언 된 친구만 이 변수에 영향을 줄 것이라는 합리적인 확신 이 있습니다. 해당 값에 합리적으로 영향을 줄 수있는 코드 범위는 제한적이고 명시 적으로 정의됩니다.

구문 보호를 피할 수있는 방법이 있습니까? 전혀; 대부분의 언어가 있습니다. C ++에서는 항상 클래스를 다른 유형으로 캐스트하고 비트를 찌를 수 있습니다. Java 및 C #에서는 자신을 반영 할 수 있습니다. 기타 등등.

그러나이 작업 은 어렵습니다 . 하지 말아야 할 일을하고있는 것이 분명합니다. 당신은 할 수없는 사고 (C 야생 쓰기의 외부 ++) 그것을 할. 당신은 기꺼이 "내 컴파일러가 말하지 않은 것을 만질 것"이라고 생각해야한다. 당신은 기꺼이 불합리한 일을해야합니다 .

구문 보호가 없으면 프로그래머는 실수로 문제를 해결할 수 있습니다. 사용자에게 컨벤션을 가르쳐야하며 매번 그 컨벤션을 따라야합니다 . 그렇지 않으면 세상은 매우 안전하지 않게됩니다.

구문 보호가 없으면 잘못된 사람들이 있습니다. 많은 사람들이 수업을 사용합니다. 그들은 협약을 따라야합니다. 그렇지 않으면 불특정 한 악이 발생할 것입니다. 스크래치 : 지정되지 않은 불량 발생할 있습니다.

잘못된 일을하면 모든 것이 잘 작동하는 API보다 나쁘지 않습니다. 사용자가 올바른 일을했는지, 모든 것이 괜찮다는 등의 잘못된 확신을 제공합니다.

그리고 그 언어를 처음 사용하는 사용자는 무엇입니까? 학생들은 실제 구문을 배우고 따라야 할뿐만 아니라 (컴파일러에 의해 적용됨) 이제이 규칙을 따라야합니다. 그렇지 않으면 나쁜 일이 일어나지 않을 것입니다. 프로그래머가 컨벤션이 존재하는 이유를 이해하지 못하면 어떻게됩니까? 그가 "나사"라고 말하면 어떻게됩니까? 그리고 모든 것이 계속 작동한다면 그는 어떻게 생각합니까?

그는 대회가 바보라고 생각합니다. 그리고 그는 다시는 그것을 따르지 않을 것입니다. 그리고 그는 모든 친구들에게도 귀찮게하지 말라고 말할 것입니다.

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