“ ผู้ใช้ไม่ควรตัดสินใจว่าเป็นผู้ดูแลหรือไม่ ควรมีสิทธิ์หรือระบบรักษาความปลอดภัย”


55

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

user.isAdmin()

สิ่งนี้กระตุ้นให้เกิดความคิดเห็นซึ่งซ้ำหลายครั้งและได้รับการโหวตหลายครั้ง:

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

ฉันตอบ

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

แต่นี่ไม่ได้ผล เห็นได้ชัดว่ามีความแตกต่างพื้นฐานของมุมมองซึ่งทำให้การสื่อสารเป็นเรื่องยาก มีคนอธิบายให้ฉันฟังได้ไหมว่าทำไม user.isAdmin () ไม่ดีและวาดภาพร่างสั้น ๆ ของสิ่งที่ดูเหมือน "ถูกต้อง"

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


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

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

2
ไม่ใช่ที่คุณถาม แต่สิ่งที่ฉันจะต้องระวังเป็นอย่างมากในกรณีนี้คือวิธี IsAdmin () ทุกที่ที่คุณใส่มัน ฉันมักจะแนะนำให้มี "ผู้ดูแลระบบ" ไม่ได้รับการกำหนดค่าตายตัว แต่มีเพียงชุดของสิทธิ์ที่เป็นไปได้และ "ผู้ดูแลระบบ" จะเกิดขึ้นกับทั้งชุด วิธีการที่เมื่อคุณจำเป็นต้องแยกบทบาทผู้ดูแลระบบต่อมาสิ่งที่มีมากได้ง่ายขึ้น และมันลดลงในตรรกะกรณีพิเศษ
psr

1
@Philipp ผมไม่คิดอย่างนั้น ... เว็บไซต์ทั้งสองอย่างชัดเจนพูดคุยเกี่ยวกับUserวัตถุที่มีisAdmin()วิธีการ (สิ่งที่มันไม่อยู่เบื้องหลัง)
Izkata

สายเกินไปที่จะแก้ไข ฉันหมายถึง "ทั้งสองข้าง" ไม่ใช่ "ทั้งสองไซต์" ... = P
Izkata

คำตอบ:


12

คิดเกี่ยวกับผู้ใช้เป็นกุญแจสำคัญและการอนุญาตเป็นค่า

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

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


40

ความคิดเห็นนั้นเป็นคำพูดที่ไม่ดี

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


6
Ouch (มันเป็นความคิดเห็นของฉัน) แต่คุณทำให้ดีกว่าที่ฉันทำ
Marjan Venema

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

2
@GlenPeterson: ไม่จำเป็นต้องเป็นแค่คลาส <> ในตารางและมักจะมีคลาสที่ต้องแยกแยะมากกว่าตาราง การมุ่งเน้นข้อมูลจะนำไปสู่การกำหนดรายการย่อยในคลาสแม้ว่าเมื่อหลายครั้งที่รายการเหล่านี้ควรจะถูกกำหนดใน "บัญชีแยกประเภท" (คำสั่งซื้อ) อื่นหรือคำสั่งบางคลาสดังกล่าวผ่านในผู้ใช้ (หรือคำสั่ง) มันเป็นเรื่องของความรับผิดชอบมากกว่าคำกริยาและคำนาม
Marjan Venema

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

2
@ Wilbert: บริบท! นั่นคือความรู้แจ้งโดยเฉพาะอย่างยิ่ง! ใช่ถ้าคุณมีมากกว่าหนึ่งบริบทสำหรับการอนุญาตเหล่านั้นทุกอย่างสมเหตุสมผลสำหรับฉัน ฉันมักจะเห็นการอนุญาตเหล่านี้ในบริบทเดียวและการผสานมันไว้กับผู้ใช้เป็นทางออกที่ง่ายที่สุดในกรณีนั้น เห็นได้ชัดว่าพวกเขาไม่ได้อยู่ที่นั่นหากพวกเขาใช้แตกต่างกันในบริบทที่สอง หากคุณเขียนว่าเป็นคำตอบฉันมีแนวโน้มที่จะยอมรับมัน ขอขอบคุณ.
GlenPeterson

30

ฉันจะไม่เลือกที่จะแสดงความคิดเห็นต้นฉบับในแบบที่มันเป็นคำ แต่มันจะระบุปัญหาที่อาจเกิดขึ้นตามกฎหมาย

โดยเฉพาะความกังวลที่รับประกันแยกมีการตรวจสอบกับการอนุมัติ

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

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

ทั้งสองนี้สามารถเปลี่ยนมุมฉากซึ่งกันและกัน ตัวอย่างเช่นคุณอาจเปลี่ยนรูปแบบการรับรองความถูกต้องโดยการเพิ่มผู้ให้บริการ OpenID / OpenAuth และคุณอาจเปลี่ยนนโยบายความปลอดภัยโดยเพิ่มบทบาทใหม่หรือเปลี่ยนจาก RBAC เป็น ABAC

หากสิ่งเหล่านี้เป็นคลาสหรือนามธรรมรหัสความปลอดภัยของคุณซึ่งเป็นหนึ่งในเครื่องมือที่สำคัญที่สุดในการลดความเสี่ยงกลายเป็นเรื่องที่มีความเสี่ยงสูง

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

ไมโครซอฟท์และซัน / ออราเคิล (Java) หมายถึงการรวมของการตรวจสอบและอนุมัติข้อมูลเป็นความปลอดภัยของเงินต้น มันไม่สมบูรณ์แบบ แต่ทำงานได้ดีพอสมควร ใน. NET ตัวอย่างเช่นคุณมีIPrincipalสิ่งที่ห่อหุ้มวัตถุIIdentity- อดีตเป็นวัตถุนโยบาย (การอนุญาต) ในขณะที่หลังเป็นตัวตน (การรับรองความถูกต้อง) คุณพอจะตั้งคำถามกับการตัดสินใจที่จะใส่หนึ่งภายในของอื่น ๆ แต่สิ่งที่สำคัญก็คือว่ารหัสที่สุดที่คุณเขียนจะเป็นเพียงหนึ่งในแนวคิดซึ่งหมายความว่ามันเป็นเรื่องง่ายในการทดสอบและ refactor

ไม่มีอะไรผิดปกติกับUser.IsAdminฟิลด์ ... เว้นแต่จะมีUser.Nameฟิลด์ด้วย สิ่งนี้จะบ่งชี้ว่าแนวคิด "ผู้ใช้" ไม่ได้ถูกกำหนดอย่างเหมาะสมและนี่เป็นเรื่องน่าเศร้าที่เกิดข้อผิดพลาดที่พบบ่อยในหมู่นักพัฒนาซอฟต์แวร์ที่เปียกหลังใบหูเมื่อพูดถึงเรื่องความปลอดภัย โดยทั่วไปสิ่งเดียวที่ควรใช้ร่วมกันโดยข้อมูลประจำตัวและนโยบายคือ ID ผู้ใช้ซึ่งไม่ได้เกิดขึ้นโดยบังเอิญคือวิธีการนำไปใช้ในรูปแบบการรักษาความปลอดภัยทั้ง Windows และ * nix

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

รูปแบบความปลอดภัยแบบง่าย ๆดูเหมือนจะเป็นความคิดที่ดีเสมอเมื่อคุณออกแบบแอปพลิเคชั่นใหม่เป็นครั้งแรกเนื่องจาก YAGNI และสิ่งนั้น แต่มันมักจะกลับมากัดคุณในภายหลังเพราะแปลกใจแปลกใจเพิ่มคุณสมบัติใหม่ ๆ !

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


11
โอ้ฉันหวังว่าฉันจะมีเวลาเขียนสิ่งนี้ จากนั้นอีกครั้งฉันอาจไม่สามารถใส่ได้เหมือนที่คุณทำโดยไม่ต้องคิดมากขึ้นในส่วนของฉัน หลายครั้งที่สัญชาตญาณของลำไส้บอกให้ฉันไปทางใดทางหนึ่ง แต่อธิบายว่าทำไม - เพื่อตัวฉันเองหรือคนอื่น - ใช้ความคิดและความพยายามมากขึ้น ขอบคุณสำหรับโพสต์นี้ จะมีหลาย plussed แต่ SE จะไม่ให้ฉัน ...
Marjan Venema

ฟังดูคล้ายกับโครงการที่ฉันกำลังทำอยู่อย่างน่าตกใจและคำตอบของคุณก็ให้มุมมองที่ต่างออกไป ขอบคุณมาก!
แบรนดอน

"ไม่มีอะไรผิดปกติกับฟิลด์ User.IsAdmin ... เว้นแต่จะมีฟิลด์ชื่อผู้ใช้" ที่คุณเขียน แต่isAdminวิธีการคืออะไร? อาจเพียงมอบหมายให้วัตถุที่มีความรับผิดชอบในการติดตามการอนุญาต แนวปฏิบัติที่ดีที่สุดในการออกแบบแบบจำลองเชิงสัมพันธ์ (เขตข้อมูลที่หน่วยงานมี) ไม่จำเป็นต้องแปลว่าแนวปฏิบัติที่ดีที่สุดในแบบจำลอง OO คืออะไร (ข้อความใดที่วัตถุสามารถตอบสนองได้)
KaptajnKold

@KaptajnKold: ฉันอ่านความรู้สึกนี้ในกระทู้ถามตอบต่างๆในฟอรัมนี้ หากวิธีการที่มีอยู่ก็ไม่ได้สำคัญว่าจะโดยตรงดำเนินการการดำเนินงานหรือผู้ได้รับมอบหมายพวกเขาก็ยังนับว่าเป็นความรับผิดชอบเพราะชั้นเรียนอื่น ๆ อาจต้องพึ่งพามัน คุณUser.IsAdminอาจเป็นสายการบินเดียวที่ไม่ทำอะไรเลยนอกจากโทรPermissionManager.IsAdmin(this.Id)แต่ถ้าได้รับการอ้างอิงโดยคลาสอื่น 30 คลาสคุณจะไม่สามารถเปลี่ยนหรือลบมันได้ นั่นเป็นเหตุผลที่ SRP มีอยู่จริง
Aaronaught

และ @KaptajnKold เท่าที่โมเดลเชิงสัมพันธ์ไปแล้วฉันไม่แน่ใจว่าคุณกำลังทำอะไรอยู่ ก็จะยิ่งเลวร้ายที่จะมีข้อมูลIsAdmin มันเป็นประเภทของสนามที่มีแนวโน้มที่จะติดอยู่นานหลังจากที่ระบบได้พัฒนาเป็น RBAC หรือสิ่งที่ซับซ้อนมากขึ้นและค่อยๆซิงค์กับสิทธิ์ "ของจริง" และผู้คนลืมว่าพวกเขาไม่ควรใช้มันอีกต่อไป และ ... ก็แค่บอกว่าไม่ แม้ว่าคุณคิดว่าคุณมีเพียงสองบทบาทคือ "ผู้ดูแลระบบ" และ "ผู้ดูแลระบบ" อย่าเก็บไว้เป็นเขตข้อมูลบูลีน / บิตทำให้เป็นมาตรฐานปกติและมีตารางสิทธิ์
Aaronaught

28

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

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


2
@GlenPeterson: ไม่ผู้ใช้สามารถดำรงอยู่ได้เป็นอย่างดีโดยไม่มีความปลอดภัย แล้วชื่อของฉันชื่อที่แสดงที่อยู่ของฉันที่อยู่อีเมลและอื่น ๆ ของคุณคุณจะใส่ไว้ที่ไหน บัตรประจำตัว (รับรองความถูกต้อง) และการอนุญาตเป็นสัตว์ที่แตกต่างกันโดยสิ้นเชิง
Marjan Venema

2
class Userเป็นองค์ประกอบหลักในการรักษาความปลอดภัยของแฝดประจำตัวประชาชน, การตรวจสอบการอนุมัติ สิ่งเหล่านี้มีความสัมพันธ์ใกล้ชิดกับระดับการออกแบบดังนั้นจึงไม่มีเหตุผลที่รหัสจะสะท้อนถึงการพึ่งพาซึ่งกันและกันนี้
MSalters

1
คำถามคือคลาสผู้ใช้ควรมีเหตุผลทั้งหมดสำหรับจัดการ triplet หรือไม่!
Zavior

3
@MSalters: ถ้ามันเป็น API ของตรรกะดังกล่าวมันรู้เกี่ยวกับมันแม้ว่ามันจะมอบหมายให้ผู้อื่นในตรรกะที่แน่นอน ประเด็นที่ต้องทำคือการอนุญาต (การอนุญาต) เป็นเรื่องของการรวมกันของผู้ใช้กับสิ่งอื่นและดังนั้นจึงไม่ควรเป็นส่วนหนึ่งของผู้ใช้หรืออย่างอื่น แต่เป็นส่วนหนึ่งของระบบการอนุญาตที่ตระหนักถึงทั้งผู้ใช้และสิ่งใดก็ตาม กำลังได้รับอนุญาตให้
Marjan Venema

2
Should there be changes- ดีเราไม่ทราบว่าจะมีการเปลี่ยนแปลง YAGNI และทั้งหมด ทำการเปลี่ยนแปลงเหล่านั้นเมื่อจำเป็นหรือไม่
Izkata

10

ฉันคิดว่าปัญหาที่เกิดขึ้นอาจเป็นประโยคที่ไม่ดีคือมันทำให้น้ำหนักมากเกินไปในUserชั้นเรียน ไม่ไม่มีปัญหาด้านความปลอดภัยเมื่อมีวิธีUser.isAdmin()ตามที่แนะนำในความคิดเห็นเหล่านั้น ท้ายที่สุดถ้าใครบางคนลึกพอที่จะฉีดโค้ดที่เป็นอันตรายสำหรับคลาสหลักของคุณคุณมีปัญหาร้ายแรง ในทางกลับกันมันไม่สมเหตุสมผลที่Userจะตัดสินใจว่ามันเป็นผู้ดูแลระบบสำหรับทุกบริบทหรือไม่ ลองนึกภาพว่าคุณเพิ่มบทบาทที่แตกต่าง: ผู้ดูแลสำหรับฟอรัมของคุณผู้แก้ไขที่สามารถเผยแพร่โพสต์ในหน้าแรก, นักเขียนที่สามารถเขียนเนื้อหาเพื่อให้ผู้เผยแพร่สามารถเผยแพร่และอื่น ๆ ด้วยวิธีการวางมันลงบนUserวัตถุคุณจะจบลงด้วยวิธีการมากเกินไปและตรรกะที่มากเกินไปที่อาศัยอยู่ในสิ่งUserที่ไม่เกี่ยวข้องโดยตรงกับชั้นเรียน

แต่คุณสามารถใช้สิทธิ์ enum ประเภทต่างๆและPermissionsManagerคลาสแทน บางทีคุณอาจมีวิธีการเช่นPermissionsManager.userHasPermission(User, Permission)คืนค่าบูลีน ในทางปฏิบัติมันอาจดูเหมือน (ใน java):

if (!PermissionsManager.userHasPermission(user, Permissions.EDITOR)) {
  Site.renderSecurityRejectionPage();
}

มันเทียบเท่ากับวิธีการของรางbefore_filterซึ่งให้ตัวอย่างของการตรวจสอบสิทธิ์ประเภทนี้ในโลกแห่งความเป็นจริง


6
มันแตกต่างจากuser.hasPermission(Permissions.EDITOR)อย่างไรยกเว้นว่ามันมีความละเอียดและขั้นตอนมากกว่า OO?
Cephalopod

9
@Arian: เนื่องจากuser.hasPermissionsมีความรับผิดชอบมากเกินไปในคลาสผู้ใช้ มันจำเป็นที่ผู้ใช้ต้องทราบเกี่ยวกับการอนุญาตในขณะที่ผู้ใช้ (คลาส) จะสามารถมีอยู่ได้โดยปราศจากความรู้เช่นนั้น คุณไม่ต้องการให้คลาสผู้ใช้รู้เกี่ยวกับวิธีการพิมพ์หรือการแสดงผล (สร้างฟอร์ม) ด้วยตัวคุณเองคุณสามารถปล่อยให้คลาสเครื่องพิมพ์ renderer / builder หรือ display renderer / builder แสดงผลได้
Marjan Venema

4
user.hasPermission(P)เป็น API ที่ถูกต้อง แต่นั่นเป็นเพียงส่วนต่อประสาน แน่นอนการตัดสินใจที่แท้จริงจะต้องทำในระบบย่อยการรักษาความปลอดภัย เพื่อระบุความคิดเห็นของ syrion เกี่ยวกับการทดสอบในระหว่างการทดสอบคุณสามารถสลับระบบย่อยนั้นได้ อย่างไรก็ตามข้อดีของการใช้งานที่ตรงไปตรงมาuser.hasPermission(P)ก็คือคุณไม่ได้สร้างรหัสทั้งหมดเพื่อให้คุณสามารถทดสอบclass Userได้
MSalters

3
@MarjanVenema โดยตรรกะนั้นผู้ใช้จะยังคงเป็นวัตถุข้อมูลที่ไม่มีความรับผิดชอบเลย ฉันไม่ได้บอกว่าควรใช้การจัดการสิทธิ์ทั้งหมดในคลาสผู้ใช้หากมีความต้องการระบบที่ซับซ้อน คุณบอกว่าผู้ใช้ไม่จำเป็นต้องรู้เกี่ยวกับการอนุญาต แต่ฉันไม่เห็นว่าทำไมทุก ๆ คลาสอื่น ๆ จำเป็นต้องรู้วิธีการแก้ไขสิทธิ์สำหรับผู้ใช้ สิ่งนี้ทำให้การเยาะเย้ยและทดสอบยากขึ้นมาก
Cephalopod

6
@Arian: ในขณะที่คลาส anemic เป็นกลิ่นบางคลาสก็ไม่มีพฤติกรรมใด ๆ ... ผู้ใช้ imho เป็นคลาสหนึ่งที่ดีกว่าใช้เป็นพารามิเตอร์สำหรับกลุ่มอื่น ๆ ทั้งหมด (ผู้ที่ต้องการทำสิ่งต่าง ๆ / ตัดสินใจจากผู้ที่ถามพวกเขา) แทนที่จะถูกใช้เป็นที่เก็บของพฤติกรรมทุกประเภทเพียงเพราะมันสะดวกที่จะเขียนโค้ดเช่นนั้น
Marjan Venema

9

Object.isX () ใช้เพื่อแสดงความสัมพันธ์ที่ชัดเจนระหว่างวัตถุและ X ซึ่งสามารถแสดงเป็นผลลัพธ์บูลีนตัวอย่างเช่น:

Water.isBoiling ()

Circuit.isOpen ()

User.isAdmin () ถือว่าความหมายเดียวของ 'ผู้ดูแลระบบ' ในทุกบริบทของระบบซึ่งผู้ใช้เป็นผู้ดูแลระบบในทุกส่วนของระบบ

ในขณะที่ฟังดูง่ายพอโปรแกรมโลกแห่งความเป็นจริงแทบจะไม่เหมาะกับโมเดลนี้แน่นอนที่สุดจะมีข้อกำหนดสำหรับผู้ใช้ในการจัดการทรัพยากร [X] แต่ไม่ใช่ [Y] หรือสำหรับผู้ดูแลระบบประเภทต่าง ๆ (โครงการ ] ผู้ดูแลระบบเทียบกับผู้ดูแลระบบ [ระบบ])

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


6

โปสเตอร์มีเพียงการออกแบบที่แตกต่างและซับซ้อนมากขึ้นในใจ ในความคิดของฉันUser.isAdmin()เป็นเรื่องปกติ แม้ว่าคุณจะต่อมาแนะนำบางรุ่นสิทธิ์ซับซ้อน, ฉันเห็นเหตุผลเล็ก ๆ น้อย ๆ User.isAdmin()ที่จะย้าย ในภายหลังคุณอาจต้องการแบ่งคลาสผู้ใช้เป็นวัตถุที่แสดงถึงผู้ใช้ที่เข้าสู่ระบบและวัตถุคงที่ที่แสดงข้อมูลเกี่ยวกับผู้ใช้ หรือคุณอาจไม่ บันทึกพรุ่งนี้เพื่อพรุ่งนี้


4
Save tomorrow for tomorrow. ใช่. เมื่อคุณคิดออกว่ารหัสคู่แน่นคุณเพียงแค่เขียนได้ชุกคุณและคุณจะต้องเขียนมันเพราะคุณไม่ได้ใช้เวลาพิเศษ 20 นาทีจะแยกมัน ...
MirroredFate

5
@MirroredFate: เป็นไปได้ทั้งหมดที่จะมีUser.isAdminวิธีการเชื่อมต่อกับกลไกการอนุญาตตามอำเภอใจโดยไม่ต้องเชื่อมคลาสผู้ใช้กับกลไกเฉพาะนั้น
วินไคลน์

3
สำหรับ User.isAdmin ที่จะเชื่อมต่อกับกลไกการอนุญาตตามอำเภอใจแม้จะไม่มีการเชื่อมต่อกับกลไกที่เฉพาะเจาะจงก็ตาม ต่ำสุดซึ่งจะเป็นอินเทอร์เฟซ และอินเทอร์เฟซนั้นไม่ควรอยู่ที่นั่น มันเป็นการให้คลาสผู้ใช้ (และอินเทอร์เฟซ) บางสิ่งที่ไม่ควรรับผิดชอบ Aaronaughtอธิบายได้ดีกว่าฉันมาก (เช่นการรวมกันของคำตอบอื่น ๆ ทั้งหมดสำหรับคำถามนี้)
Marjan Venema

8
@ MirroredFate: ฉันไม่สนใจว่าฉันต้องเขียนการใช้งานง่าย ๆ เพื่อตอบสนองความต้องการที่ซับซ้อนมากขึ้น แต่ฉันมีประสบการณ์ไม่ดีจริง ๆ กับ API ที่ซับซ้อนมากเกินไปที่ออกแบบมาเพื่อตอบสนองความต้องการในอนาคตที่จินตนาการไว้ซึ่งไม่เคยเกิดขึ้นมาก่อน
วินไคลน์

3
@kevincline ในขณะที่ API ที่ซับซ้อนเกินไปนั้นเป็นสิ่งที่ไม่ดี (โดยคำจำกัดความ) ฉันไม่ได้แนะนำว่าควรเขียน API ที่ซับซ้อนมากเกินไป ฉันระบุว่าSave tomorrow for tomorrowเป็นวิธีการออกแบบที่แย่มากเพราะมันทำให้เกิดปัญหาที่ไม่สำคัญหากระบบถูกนำไปใช้อย่างถูกต้อง ในความเป็นจริงความคิดนั้นเป็นผลลัพธ์ของ API ที่มีความซับซ้อนมากเกินไปเนื่องจากมีการเพิ่มเลเยอร์ลงบนเลเยอร์เพื่อแก้ไขการออกแบบเริ่มต้นที่ไม่ดี measure twice, cut onceผมคิดว่าท่าทางของฉันคือ
MirroredFate

5

ไม่เป็นปัญหา ...

User.isAdmin()ฉันไม่เห็นปัญหากับ ฉันชอบมันPermissionManager.userHasPermission(user, permissions.ADMIN)มากกว่าซึ่งในชื่อศักดิ์สิทธิ์ของ SRP ทำให้รหัสชัดเจนน้อยลงและไม่เพิ่มมูลค่าใด ๆ

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

... แต่ทำไมคุณถึงอยากรู้

ที่กล่าวมาดูเหมือนว่าฉันจะไม่ค่อยรู้ว่าผู้ใช้เป็นผู้ดูแลหรือไม่สามารถตอบคำถามอื่น ๆ ได้เช่นว่าผู้ใช้จะได้รับอนุญาตให้ดำเนินการบางอย่างหรือไม่เช่นอัปเดตวิดเจ็ต หากเป็นกรณีนี้ฉันต้องการมีวิธีใน Widget เช่นisUpdatableBy(User user):

boolean isUpdatableBy(User user) {
    return user.isAdmin();
}

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

[แก้ไข]

ปัญหาเกี่ยวกับการไม่ได้มีUser.isAdmin()และการใช้PermissionManager.userHasPermission(...)

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

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

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

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


2
"SRP ก็หมายความว่าวัตถุต้องมอบหมายให้ทำงานร่วมกันสิ่งที่ไม่ได้อยู่ภายในเป็นความรับผิดชอบเดียว" - เท็จ คำจำกัดความของ SRP ครอบคลุมทุกสิ่งที่วัตถุทำโดยตรงและทุกสิ่งที่ได้รับมอบหมาย คลาสที่ทำงานเพียงหนึ่งงานโดยตรง แต่ทำงานอีก 50 งานทางอ้อมผ่านการมอบหมายยังคง (อาจ) ละเมิด SRP
Aaronaught

KaptajnKold: ฉัน +1 เพราะฉันเห็นด้วยกับคุณและฉันรู้สึกผิดเล็กน้อยเกี่ยวกับเรื่องนั้น โพสต์ของคุณเพิ่มในการสนทนา แต่ไม่ตอบคำถาม
GlenPeterson

@GlenPeterson ดีผมพยายามที่จะอยู่เป็นส่วนหนึ่งของคำถามซึ่งเป็น 'สิ่งที่ดูเหมือนว่าทำ 'สิทธิ'' นอกจากนี้ยังมี: คุณควรอย่างไม่รู้สึกผิดเกี่ยวกับเห็นด้วยกับฉัน :)
KaptajnKold

1
@JamesSnell บางที ถ้า. แต่นั่นเป็นรายละเอียดการใช้งานซึ่งฉันจะยังคง จำกัด อยู่ในวิธีการ isAdmin กับผู้ใช้ วิธีนี้ทำให้รหัสลูกค้าของคุณไม่ต้องเปลี่ยนเมื่อ "admin-ness" ของผู้ใช้วิวัฒนาการจากการเป็นฟิลด์บูลีนไปเป็นบางสิ่งที่ก้าวหน้ากว่า คุณอาจมีหลาย ๆ สถานที่ที่คุณจำเป็นต้องรู้ว่าผู้ใช้เป็นผู้ดูแลระบบหรือไม่และไม่ต้องการเปลี่ยนแปลงทุกครั้งที่ระบบอนุญาตเปลี่ยน
KaptajnKold

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

1

การสนทนานี้ทำให้ฉันนึกถึงบล็อกโพสต์โดย Eric Lippert ซึ่งทำให้ฉันสนใจในการอภิปรายที่คล้ายกันเกี่ยวกับการออกแบบชั้นความปลอดภัยและความถูกต้อง

ทำไมคลาสเฟรมเวิร์คจำนวนมากถูกปิดผนึก?

โดยเฉพาะอย่างยิ่งเอริคยกประเด็น:

4) ปลอดภัย จุดรวมของความแตกต่างคือคุณสามารถผ่านวัตถุที่มีลักษณะเหมือนสัตว์ แต่ในความเป็นจริงแล้วยีราฟ มีปัญหาด้านความปลอดภัยที่อาจเกิดขึ้นที่นี่

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

นี้อาจดูเหมือนสัมผัส แต่ฉันคิดว่ามัน dovetails กับจุดโปสเตอร์อื่น ๆ ได้ยกขึ้นเกี่ยวกับSOLID หลักการเดียวรับผิดชอบ พิจารณาคลาสที่เป็นอันตรายต่อไปนี้เป็นเหตุผลที่จะไม่ใช้User.IsAdminวิธีการหรือคุณสมบัติ

public class MyUser : User
{

    public new boolean IsAdmin()
    {
        // You know it!
        return true;
    }

    // Anything else we can break today?

}

จริงอยู่มันเป็นเรื่องที่ค่อนข้างยืดเยื้อ: ยังไม่มีใครแนะนำIsAmdminวิธีการเสมือนจริง แต่อาจเกิดขึ้นได้หากสถาปัตยกรรมผู้ใช้ / บทบาทของคุณสิ้นสุดลงด้วยความซับซ้อนที่แปลกประหลาด (หรืออาจจะไม่ใช่ลองพิจารณาpublic class Admin : User { ... }: คลาสนี้อาจมีรหัสที่ด้านบน) การรับไบนารีที่เป็นอันตรายเข้ามาไม่ใช่การโจมตีแบบเวกเตอร์ทั่วไปและมีความเป็นไปได้ที่จะเกิดความสับสนวุ่นวายมากกว่าห้องสมุดผู้ใช้ที่คลุมเครือ อาจเป็นข้อผิดพลาดของการเพิ่มระดับสิทธิ์ที่เปิดประตูสู่ความเป็นจริงของเชนันนิแกน ในที่สุดหากอินสแตนซ์ไบนารีหรือวัตถุที่เป็นอันตรายไม่สามารถหาเวลามาใช้งานได้มันก็ไม่ได้ไกลเกินกว่าที่จะจินตนาการว่า "Privilege หรือระบบรักษาความปลอดภัย" ถูกแทนที่ในลักษณะที่คล้ายคลึงกัน

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

โอ้และเพื่อความแม่นยำสำหรับบันทึกฉันเห็นด้วยกับสัจพจน์ในคำถาม:“ ผู้ใช้ไม่ควรตัดสินใจว่าเป็นผู้ดูแลระบบหรือไม่ . สิทธิประโยชน์หรือการรักษาความปลอดภัยระบบควร” เป็นUser.IsAdminวิธีการที่เป็นความคิดที่ไม่ดีถ้าคุณกำลังเรียกใช้รหัสในระบบของคุณไม่ได้อยู่ในการควบคุม 100% ของรหัส - Permissions.IsAdmin(User user)คุณแทนควรจะทำอย่างไร


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

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

ฉันไม่แน่ใจว่าทำไมคุณพูดอย่างนั้น กรอบความปลอดภัยและการอนุญาตจำนวนมากนั้นสามารถขยายได้อย่างมาก แกนหลัก. NET ส่วนใหญ่ที่เกี่ยวข้องกับความปลอดภัย (IPrincipal, IIdentity, ClaimSet ฯลฯ ) ไม่เพียง แต่ไม่ได้ปิดผนึกเท่านั้น แต่ยังอยู่ในอินเทอร์เฟซจริงหรือคลาสนามธรรมเพื่อให้คุณสามารถเสียบอะไรก็ได้ที่คุณต้องการ สิ่งที่เอริคกำลังพูดถึงคือคุณไม่ต้องการให้มันเป็นสิ่งSystem.Stringที่สืบทอดได้เพราะรหัสเฟรมเวิร์กที่สำคัญทุกชนิดทำให้สมมติฐานที่เฉพาะเจาะจงมากเกี่ยวกับวิธีการทำงาน ในทางปฏิบัติส่วนใหญ่ "รหัสผู้ใช้" (รวมถึงการรักษาความปลอดภัย) เป็นสิ่งที่สืบทอดได้เพื่อให้สามารถทดสอบได้สองเท่า
Aaronaught

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

ฉันรู้ว่ามันไม่ได้กล่าวถึง แต่หลักการของความรับผิดชอบในชั้นเรียนนั้นเกี่ยวข้องโดยตรงกับความแตกต่างหลากหลาย หากไม่มีIsAdminวิธีการแทนที่ / เลือกร่วมไม่มีช่องโหว่ด้านความปลอดภัย ตรวจสอบวิธีการของอินเทอร์เฟซระบบเหล่านั้นIPrincipalและIIdentityเป็นที่ชัดเจนว่าผู้ออกแบบไม่เห็นด้วยกับฉันและฉันก็ยอมรับประเด็นนี้
Patrick M

0

ปัญหาที่นี่คือ:

if (user.isAdmin()) {
   doPriviledgedOp();
} else {
   // maybe we can anyway!
   doPriviledgedOp();
}

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


4
คลาสที่ไม่มีสิทธิพิเศษคืออะไร
แบรนดอน

1
ไม่มีสิ่งใดที่คุณสามารถทำได้เพื่อป้องกันไม่ให้เขียนโค้ดประเภทนี้ ไม่ว่าคุณจะออกแบบแอพของคุณที่ไหนสักแห่งจะต้องมีการตรวจสอบอย่างชัดเจนเช่นนี้และบางคนอาจเขียนให้ไม่ปลอดภัย แม้ว่าระบบการอนุญาตของคุณจะได้รับการปรับปรุงให้ดีขึ้นเหมือนกับการตกแต่งวิธีที่มีบทบาทหรือคุณลักษณะการอนุญาต แต่บางคนอาจโยนสิทธิ์ "สาธารณะ" หรือ "ทุกคน" อย่างไม่ถูกต้อง ดังนั้นฉันไม่เห็นว่าวิธีนี้ทำให้เกิดปัญหาอย่างUser.IsAdmin เฉพาะเจาะจงได้อย่างไร
Aaronaught
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.