หลักปฏิบัติมาตรฐานสำหรับการควบคุมการเข้าถึง (รูปแบบการออกแบบ)


9

ฉันกำลังดูที่การออกแบบส่วนต่อประสานของฉันและฉันพยายามที่จะตัดสินใจว่าวิธีใดที่ "ถูกต้อง" ที่สุดในการใช้การควบคุมการเข้าถึงตามบทบาทซึ่งกำหนดไว้userและสิ่งsubjectที่userต้องการเข้าถึง


เท่าที่ฉันเห็นฉันมีสามตัวเลือกหลัก (ที่สี่เป็นลูกครึ่งของสามสามและห้าเป็นบิดของสี่):

  1. ค้นหาsubjectด้วยรายการสิทธิ์ที่userมี -subject.allowAccess(user.getPermissionSet)
  2. ค้นหาuserด้วยรายการสิทธิ์ที่subjectต้องการ -user.hasPermissionTo(subject.getRequiredPermissions())
  3. สอบถามบุคคลที่สามเพื่อค้นหาจุดตัดสิทธิ์ - accessController.doPermissionSetsIntersect(subject.permissionSet, user.getPermissionSet())
  4. ค้นหาทั้งsubject/ userในขณะที่มอบหมาย "การตัดสินใจ" ให้กับบุคคลที่สามชั้น
  5. มีuserความพยายามในการเข้าถึงsubjectและโยนข้อผิดพลาดหากไม่ได้รับอนุญาต

ฉันกำลังเอนเอียงไปทางตัวเลือกที่สี่ - มีsubjectประกอบด้วยaccessControllerข้อมูลที่โทรไปยังsubject.userMayAccess(User user)มอบหมายการดำเนินการแบบ a la:

class Subject {
    public function display(user) {
        if(!accessController.doPermissionSetsIntersect(this.permissionSet, user.getPermissionSet())) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

.. แต่เมื่อถามคำถามเพิ่มเติม:

  • accessControllerฟิลด์ควรเป็นคลาสคงที่ ..
  • ควรsubject รู้ว่าต้องใช้การอนุญาตใดเพื่อให้สามารถดูได้
  • สถานที่ที่ไม่หลักการของความรู้น้อยเข้ามาเล่นที่นี่ด้วยความเคารพโทรsubject.display()? ผู้โทรควรsubject.display()ทราบหรือไม่ว่าการควบคุมการเข้าถึงมีผลใช้งานหรือไม่ (ซึ่งsubject.display()เป็น "วิธีการแบบสุดท้าย")
  • มีsubject.display()การจัดการควบคุมการเข้าถึงโดยมีข้อยกเว้นเมื่อผู้ใช้ไม่ได้รับอนุญาตที่จำเป็น?

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

เนื่องจากนี่เป็นทั้งการออกกำลังกายทางวิชาการซึ่งจะนำไปสู่การดำเนินการดังนั้นการอ้างอิงถึงรูปแบบการออกแบบจะได้รับการชื่นชม

คำตอบ:


7

แนวทางปฏิบัติที่ดีที่สุดคือการใช้สิ่งที่เรียกว่ารูปแบบ Interceptor เพื่อสกัดกั้นการโทรไปยังพื้นที่คุ้มครอง

สิ่งนี้สามารถทำได้โดยการใช้ AOP หรือข้อกังวลตัดขวางที่ใช้กับจุดเข้าใช้งานของคุณ

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

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

หากคุณใช้รูปแบบ AOP หรือรูปแบบ Interceptor มันจะส่งข้อยกเว้นที่จำเป็นออกไปและมันจะขึ้นอยู่กับลูกค้า (ผู้เรียก) เพื่อจัดการกับข้อยกเว้นที่เกิดขึ้น

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



2

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

class Subject {
    public function display(user) {
        if(!accessController.checkAccess(this, user, AccessControl.Read)) {
            display403(); //Or other.. eg, throw an error..
        }
    }
}

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

องค์ประกอบอื่น ๆ ที่อาจหายไปจากตัวอย่างของคุณคือการดำเนินการใด ผู้ใช้บางคนอาจจะมีสิทธิ์ในการอ่านข้อมูลบางอย่าง แต่ไม่ได้ไปปรับปรุงลบรัน ฯลฯ ดังนั้นคุณอาจมีcheckAccessวิธีการในการควบคุมการเข้าถึงด้วยสามพารามิเตอร์: user, ,subject operationคุณอาจต้องการให้ข้อมูลเพิ่มเติมจากcheckAccessเพื่อส่งคืนข้อมูลเกี่ยวกับสาเหตุที่ไม่อนุญาตให้เข้าถึง

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

ไม่ว่าคุณจะใช้ AOP หรือรหัส boilerplate เพื่อเสียบสิ่งนี้ในความคิดของฉันมีความสำคัญน้อยกว่า

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