วิธีส่วนตัวปลอดภัยจริงหรือ?


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

ในขณะนี้ฉันคิดว่าวิธีการส่วนตัวยังปลอดภัยเนื่องจากจะทำบางสิ่งเช่นข้างต้นเราต้องรู้ชื่อวิธีการ แต่ถ้าคลาสที่มีเมธอดส่วนตัวที่เขียนโดยคนอื่นเราไม่สามารถมองเห็นได้

แต่ประเด็นของฉันไม่ถูกต้องเนื่องจากด้านล่างบรรทัดของรหัส

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

ตอนนี้สิ่งนี้method[]มีทุกสิ่งที่ต้องทำข้างต้น คำถามของฉันคือมีวิธีหลีกเลี่ยงสิ่งประเภทนี้โดยใช้การสะท้อนของ Java หรือไม่?

ฉันอ้างบางประเด็นจากเอกสาร Javaเพื่อชี้แจงคำถามของฉัน

เคล็ดลับในการเลือกระดับการเข้าถึง:

หากโปรแกรมเมอร์คนอื่นใช้คลาสของคุณคุณต้องแน่ใจว่าข้อผิดพลาดจากการใช้ผิดประเภทจะไม่เกิดขึ้น ระดับการเข้าถึงสามารถช่วยคุณได้ใช้ระดับการเข้าถึงที่ จำกัด ที่สุดที่เหมาะสมสำหรับสมาชิกบางคน ใช้ส่วนตัวเว้นแต่คุณจะมีเหตุผลที่ดีที่จะไม่ทำ


1
การใช้ obfuscator อาจช่วยได้เพราะgetDeclaredMethodsจะส่งคืนชื่อที่ดูเหมือนขยะ
Sergey Kalinichenko

213
ส่วนบุคคลที่ได้รับการคุ้มครองสาธารณะ ฯลฯ ไม่ใช่เพื่อความปลอดภัย แต่เป็นการหลีกเลี่ยงไม่ให้คนทำผิดพลาด อย่าใช้เป็นมาตรการรักษาความปลอดภัย
Richard Tingle

20
โค้ด Java สามารถถอดรหัสได้อยู่ดี 'ผู้โจมตี' สามารถดาวน์โหลดตัวถอดรหัส Java และอ่านโค้ดของคุณหรือเปลี่ยน 'ส่วนตัว' เป็น 'สาธารณะ'
11684

7
เพื่ออธิบายสิ่งที่ @RichardTingle แสดงความคิดเห็น (+1 btw) มีความแตกต่างที่สำคัญและสำคัญระหว่างความปลอดภัยและความปลอดภัย ในกรณีหลังคือปัญหาที่บรรเทาลงด้วยตัวปรับการเข้าถึง ไม่ทำของพังโดยไม่ตั้งใจ
ผู้ใช้

3
ทั้งหมดนี้ค่อนข้างชัดเจนสำหรับโปรแกรมเมอร์ที่ไม่มีตัวปรับแต่งการเข้าถึงเช่นใน Python ในภาษาเหล่านี้ private / public มีความโดดเด่นด้วยการประชุมในชื่อ (ใน python สิ่งที่ขึ้นต้นด้วยขีดล่างเดียวควรถือว่าเป็นส่วนตัว) สิ่งนี้ทำให้ชัดเจนว่าการทำเครื่องหมายบางอย่างเป็น "ส่วนตัว" ไม่ได้เพิ่มความปลอดภัยใด ๆ แต่เป็นเพียงวิธีง่ายๆในการบอกว่าผู้คนควรใช้ API ของคุณอย่างไร ฉันมีข้อสงสัยว่าการมีคอมไพเลอร์ตรวจสอบสิ่งนี้ช่วยได้ทั้งหมดเพราะมันง่ายมากที่จะปฏิบัติตามอนุสัญญาโดยไม่ได้รับความช่วยเหลือจาก "ภายนอก"
Bakuriu

คำตอบ:


95

ขึ้นอยู่กับความหมายของคำว่า "ปลอดภัย" หากคุณใช้งานกับผู้จัดการความปลอดภัยที่อนุญาตให้ทำสิ่งนี้ได้ใช่คุณสามารถทำสิ่งที่น่ารังเกียจทุกประเภทด้วยการไตร่ตรอง แต่ในสภาพแวดล้อมแบบนั้นไลบรารีก็อาจถูกปรับเปลี่ยนเพื่อทำให้เมธอดเป็นสาธารณะได้

การควบคุมการเข้าถึงเป็น "คำแนะนำ" อย่างมีประสิทธิภาพในสภาพแวดล้อมเช่นนั้นคุณเชื่อมั่นว่าโค้ดจะเล่นได้ดี หากคุณไม่เชื่อถือรหัสที่คุณกำลังเรียกใช้คุณควรใช้ตัวจัดการความปลอดภัยที่เข้มงวดกว่านี้


3
ฉันรู้ว่าเป็นเรื่องเข้าใจได้ แต่คุณช่วยอธิบายให้ละเอียดได้ไหมว่าผู้จัดการที่เข้มงวดกว่านี้จะเป็นอย่างไร
สีเทา

12
@Gray: ตัวอย่างของSecurityManagerซึ่งมีข้อยกเว้นในการcheck*โทรที่เกี่ยวข้องโดยทั่วไป
Jon Skeet

40

ตัวปรับแต่งการเข้าถึงไม่มีส่วนเกี่ยวข้องกับความปลอดภัย ในความเป็นจริงคุณสามารถและควรมองว่าตัวปรับแต่งการเข้าถึงเป็นสิ่งที่ตรงกันข้ามกับการรักษาความปลอดภัย - ไม่ใช่เพื่อปกป้องข้อมูลหรืออัลกอริทึมของคุณ แต่เป็นการปกป้องผู้คนจากความต้องการที่จะรู้เกี่ยวกับข้อมูลและอัลกอริทึมของคุณ นี่คือสาเหตุที่โมดิฟายเออร์เริ่มต้นคือแพ็กเกจ - หากพวกเขาทำงานกับแพ็กเกจพวกเขาอาจจำเป็นต้องรู้อยู่แล้ว

นอกเหนือจากความรู้เกี่ยวกับข้อมูลและวิธีการของรหัสของคุณแล้วความสามารถในการตอบสนองที่จะทราบว่าจะใช้เมื่อใดและอย่างไร คุณไม่ให้ความเป็นส่วนตัวในเมธอด inIt ของคุณเพื่อป้องกันไม่ให้ใครรู้เรื่องนี้คุณทำเช่นนั้นเพราะ (ก) พวกเขาจะไม่รู้ว่าคุณเรียกสิ่งนั้นตามหลัง foo เท่านั้นและถ้า bar = 3.1415 และ (b) เพราะมันทำให้พวกเขาไม่รู้เรื่องนี้

modifers เข้าถึงสามารถสรุปได้ในวลีง่าย "TMI ครับผมจึงไม่จำเป็นต้องรู้ว่า"


3
คำตอบที่ดี แต่ฉันจำเป็นต้องใช้ Google เพื่อค้นหาว่า TMI หมายถึงข้อมูลที่มากเกินไป ฉันเดาว่าฉันต้องใช้เวลามากกว่านี้ในหุบเขา :-)
mikelong

7

การพูดว่า 'ปลอดภัย' แสดงว่าคุณกำลังปกป้องคุณหรือนักพัฒนาคนอื่น ๆ ซึ่งกำลังใช้ API ของคุณเพื่อไม่ให้ทำอันตรายกับวัตถุโดยการเรียกวิธีส่วนตัวของคุณ แต่ถ้าคุณหรือพวกเขาต้องการเรียกวิธีนี้จริงๆก็สามารถทำได้ด้วย Reflection


6

คำถามคือคุณพยายามช่วยชีวิตใคร ในความคิดของฉันไคลเอนต์ของรหัสของคุณคือผู้ที่สูญเสียที่นี่

รหัสชิ้นส่วนใด ๆ (เขียนโดยคุณหรือคนอื่น ๆ ) ที่พยายามเข้าถึงprivateสมาชิกของคลาสข้างต้นนั้นกำลังขุดหลุมฝังศพของตัวเองเป็นหลัก privateสมาชิกไม่ได้เป็นส่วนหนึ่งของAPI สาธารณะและอาจเปลี่ยนแปลงได้โดยไม่ต้องแจ้งให้ทราบล่วงหน้า หากลูกค้าเกิดใช้สมาชิกส่วนตัวดังกล่าวในลักษณะที่ระบุไว้ข้างต้นมันจะพังหากอัปเกรดเป็น API เวอร์ชันใหม่กว่าซึ่งสมาชิกส่วนตัวได้รับการแก้ไข


5

ด้วยสิ่งอำนวยความสะดวกมีความรับผิดชอบ นอกจากนี้สิ่งที่เป็นคุณไม่สามารถทำและสิ่งที่คุณสามารถทำได้ แต่คุณไม่ควรทำ

ตัวปรับแต่งส่วนตัวมีให้ / ใช้เป็น / ในลักษณะที่ จำกัด มากที่สุด สมาชิกที่ไม่ควรมองเห็นนอกชั้นเรียนจะถูกกำหนดให้เป็นส่วนตัว แต่สิ่งนี้สามารถหักด้วย Reflection อย่างที่เราเห็น แต่ไม่ได้หมายความว่าคุณไม่ควรใช้ส่วนตัว - หรือไม่ปลอดภัย เป็นเรื่องเกี่ยวกับคุณจะใช้สิ่งต่างๆอย่างรอบคอบหรือในเชิงสร้างสรรค์ (เช่นการไตร่ตรอง)


5

สมมติว่าคุณไว้วางใจโปรแกรมเมอร์ไคลเอนต์ของ API ของคุณอีกวิธีหนึ่งในการดูว่า 'ปลอดภัย' แค่ไหนที่พวกเขาจะใช้ฟังก์ชันเฉพาะเหล่านั้น

ฟังก์ชั่นที่เผยแพร่ต่อสาธารณะของคุณควรมีอินเทอร์เฟซที่ชัดเจนมีเอกสารดีและไม่ค่อยเปลี่ยนแปลงในโค้ดของคุณ ฟังก์ชันส่วนตัวของคุณถือได้ว่าเป็นรายละเอียดการใช้งานและอาจมีการเปลี่ยนแปลงเมื่อเวลาผ่านไปดังนั้นจึงไม่ปลอดภัยที่จะใช้โดยตรง

หากโปรแกรมเมอร์ไคลเอนต์ออกนอกลู่นอกทางเพื่อหลีกเลี่ยงสิ่งที่เป็นนามธรรมเหล่านี้แสดงว่าพวกเขารู้ว่ากำลังทำอะไรอยู่ ที่สำคัญพวกเขาเข้าใจว่าไม่รองรับและอาจหยุดทำงานกับโค้ดของคุณในอนาคต


5

privateไม่ใช่เพื่อความปลอดภัย แต่คือการรักษารหัสให้สะอาดและเพื่อป้องกันความผิดพลาด จะช่วยให้ผู้ใช้สามารถ modularize รหัส (และวิธีการที่จะพัฒนา) โดยไม่ต้องกังวลเกี่ยวกับทุกรายละเอียดของโมดูลอื่น ๆ

เมื่อคุณปล่อยรหัสของคุณผู้คนจะสามารถทราบได้ว่ามันทำงานอย่างไร ไม่มีวิธี "ซ่อน" ตรรกะหากคุณต้องการให้โค้ดทำงานบนคอมพิวเตอร์ในที่สุด แม้แต่การคอมไพล์เป็นไบนารีก็ยังเป็นระดับของความสับสน

ดังนั้นจึงไม่มีวิธีใดที่คุณจะสามารถตั้งค่า API ของคุณเพื่อทำสิ่งพิเศษที่คุณไม่ต้องการให้คนอื่นเรียกได้ ในกรณีของเว็บ API คุณสามารถวางเมธอดที่ต้องการควบคุมไว้ที่ฝั่งเซิร์ฟเวอร์ได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.