การประเมินโค้ดแบบไดนามิกใน Java - เคลฟเวอร์หรือเลอะเทอะ?


30

ฉันกำลังพยายามสร้างเฟรมเวิร์ก ACL ที่ยืดหยุ่นใน Java สำหรับแอปพลิเคชันของฉัน

กรอบ ACL หลายคนที่ถูกสร้างขึ้นในรายการที่อนุญาตของกฎที่กฎอยู่ในรูปแบบของการใช้: การกระทำ: ทรัพยากร ตัวอย่างเช่น,

  • "JOHN สามารถดูทรัพยากร FOOBAR-1"
  • "MARY สามารถดูทรัพยากร FOOBAR-1"
  • "MARY สามารถแก้ไขทรัพยากร FOOBAR-1"

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

  • "ผู้ใช้ทุกคนในแผนก 1 ที่มีอาวุโสกว่า 5 ปีสามารถดูทรัพยากร FOOBAR-1 ไม่ได้รับอนุญาต"
  • "ผู้ใช้ทุกคนในแผนก 2 หากวันที่หลังวันที่ 15/15/2016 สามารถดูทรัพยากร FOOBAR-2 ไม่ได้รับอนุญาต"

เมื่อคิดเป็นครั้งแรกมันจะเป็นฝันร้ายที่จะสร้างโครงสร้างของฐานข้อมูลที่สามารถจัดการกับกฎที่ซับซ้อนเช่นนี้ ดังนั้นดูเหมือนว่าฉันจะต้อง "อบ" พวกเขาลงในใบสมัครที่รวบรวมการประเมินพวกเขาสำหรับผู้ใช้แต่ละคนและจากนั้นผลิตเจ้าของ: การกระทำ:กฎทรัพยากรเป็นผลมาจากการประเมินผล ฉันต้องการหลีกเลี่ยงการอบตรรกะในแอปพลิเคชันที่รวบรวม

ดังนั้นฉันคิดของการเป็นตัวแทนของการปกครองในรูปแบบของคำกริยา : การกระทำ: ทรัพยากรที่สรุปคือการแสดงออกบูลที่กำหนดว่าผู้ใช้ที่ได้รับอนุญาต เพรดิเคตจะเป็นสตริงของนิพจน์ JavaScript ที่สามารถประเมินได้โดยเอนจิ้น Rhino ของ Java ตัวอย่างเช่น,

  • return user.getDept() == 1 && user.seniority > 5;

ในการทำเช่นนั้นภาคแสดงสามารถคงอยู่กับฐานข้อมูลได้อย่างง่ายดาย

มันฉลาดไหม มันเลอะเทอะหรือไม่ เป็นลูกเล่นนี้หรือไม่? นี่มันเกินวิศวกรรมไหม? นี่คือความปลอดภัย (เห็นได้ชัด, Java สามารถ sandbox เครื่องยนต์แรด)


8
ประโยชน์ของการพยายามผลักดันกฎเกณฑ์ทางธุรกิจเหล่านี้ลงในฐานข้อมูลแทนที่การวางตรรกะลงในแอปพลิเคชันที่คอมไพล์แล้วคืออะไร
Winston Ewert

6
@WinstonEWert การส่งออกกฎไม่จำเป็นต้องคอมไพล์ใหม่และแจกจ่ายซ้ำแอปพลิเคชันหากกฎมีการเปลี่ยนแปลงเพิ่มหรือลบออก
Twittopher


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

6
ฟังดูคล้ายกับกฎอีเมลของ Outlookซึ่งเป็นเอ็นจิ้นกฎที่กำหนดโดยผู้ใช้

คำตอบ:


37

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

ปัญหาของคุณจะสามารถแก้ไขได้ดีกว่าด้วยเครื่องยนต์กฎหรืออาจจะเป็นภาษาเฉพาะโดเมน (DSL) ดูแนวคิดเหล่านั้นไม่จำเป็นต้องบูรณาการล้อ


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

6
@Twittopher การลากเอนจิ้น JavaScript ทั้งหมดเพื่อประเมินเพรดิเคตบางอย่างยังดูเหมือนว่า 1) overkill ที่สมบูรณ์ 2) ความเสี่ยงและ 3) มีข้อผิดพลาดเกิดขึ้นกับฉัน ในกรณีที่คุณใช้==แทน===ตัวอย่างของคุณ คุณต้องการให้ความสมบูรณ์ของทัวริงจริงหรือไม่เมื่อกฎทั้งหมดควรยุติเสมอ แทนที่จะกระโดดผ่านห่วงเพื่อให้แน่ใจว่าการโต้ตอบทั้งหมดระหว่าง Java และ JavaScript เป็นเพียวทำไมคุณไม่เพียงเขียน parser ง่ายๆและล่ามอย่างที่ Kilian แนะนำ มันจะง่ายกว่าการปรับแต่งตามความต้องการและความปลอดภัยของคุณ ใช้ ANTLR หรืออะไรก็ได้
Doval

6
@Doval การเขียน DSL เล็ก ๆ ไม่ใช่วิทยาศาสตร์จรวดอย่างแน่นอนและฉันสามารถใช้ภาษาง่ายๆใน 3 ชั่วโมงถึง 5 วัน แต่ดูเหมือนว่า 1) overkill สมบูรณ์ 2) มีความเสี่ยงและ 3) มีข้อผิดพลาดเกิดขึ้นกับฉัน คุณต้องการที่จะเขียนมินิทั้งภาษาจริงๆเหรอ? ถ้ากฎทางธุรกิจบางอย่างซับซ้อนกว่าที่คาดไว้และต้องการภาษาที่มีคุณลักษณะครบถ้วน คุณกำลังทุกข์ทรมานจากโรคที่ไม่ได้คิดค้นที่นี่หรือไม่? แทนที่จะปรับเปลี่ยนวงล้อทำไมคุณไม่ใช้ภาษาที่มีอยู่ มันง่ายกว่ามากในการใช้ภาษาที่ผ่านการทดสอบการต่อสู้แล้ว
amon

14
@amon เมื่อสิ่งนั้นเกิดขึ้นคุณจะพบเอ็นจินกฎจริง (ซึ่งไม่ใช่ JavaScript) อย่างที่ Killian กล่าว เพื่อให้เท่ากันความเสี่ยงของทั้งสองวิธีนั้นทำให้เข้าใจผิด การละเว้นเพียงครั้งเดียวจะทำลายความพยายามทั้งหมดของคุณในการรักษาล่ามให้เป็นภาษาที่สมบูรณ์ มันเป็นกระบวนการลบ มันยากมากที่จะทำให้ DSL เล็ก ๆ เป็นอันตรายโดยไม่ได้ตั้งใจ มันเป็นกระบวนการเสริม ประเภทของข้อผิดพลาดที่คุณน่าจะทำคือการตีความโครงสร้างไวยากรณ์อย่างไม่ถูกต้องและสามารถทดสอบหน่วยได้ คุณอาจไม่ได้ตั้งใจให้ล่ามกับความสามารถในการฟอร์แมตฮาร์ดไดรฟ์
Doval

4
@ มอน: ถึงแม้ว่าข้อมูลโค้ด js อาจไม่มีผลข้างเคียงก็สามารถเลือกที่จะไม่คืนค่าบูลีน:while (true) ;
Bergi

44

ฉันทำสิ่งนี้และฉันขอแนะนำให้คุณทำ

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

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

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


3

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

กล่าวอีกนัยหนึ่งถ้าคุณมีหมายเลขแผนกมันจะง่ายกว่าถ้ามีแผนกผู้ใช้ตรวจสอบและวันนี้วันที่หลังจากตรวจสอบแล้วรวมเข้ากับแผนก = 2 และวันนี้> 03/15/2016 ถ้าคุณต้องการมีวันนี้ก่อนตรวจสอบเพื่อให้คุณสามารถสิ้นสุดวันที่ได้รับอนุญาตคุณต้องเขียนฟังก์ชัน TodayIsBefore

ฉันไม่ได้ทำสิ่งนี้เพื่อการอนุญาตของผู้ใช้ แต่ได้ทำการตรวจสอบข้อมูลแล้ว แต่ควรใช้งานได้


2

XACML เป็นโซลูชันที่คุณกำลังมองหา เป็นเอ็นจินกฎประเภทหนึ่งที่มุ่งเน้นที่การควบคุมการเข้าถึงเท่านั้น XACML มาตรฐานที่กำหนดโดย OASIS กำหนดสามส่วนดังนี้

  • สถาปัตยกรรม
  • ภาษานโยบาย (ซึ่งเป็นสิ่งที่คุณต้องการจริงๆ)
  • รูปแบบการร้องขอ / ตอบสนอง (วิธีที่คุณขอการตัดสินใจอนุมัติ)

สถาปัตยกรรมดังต่อไปนี้:

  • จุดตัดสินใจนโยบาย (PDP) เป็นส่วนสำคัญของสถาปัตยกรรม มันเป็นองค์ประกอบที่ประเมินคำขอการอนุญาตที่เข้ามากับชุดของนโยบายที่รู้จัก
  • จุดบังคับใช้นโยบาย (PEP) คือชิ้นส่วนของรหัสที่ป้องกันแอปพลิเคชัน / API / บริการของคุณ PEP สกัดกั้นคำขอธุรกิจสร้างคำขออนุญาต XACML ส่งออกไปยัง PDP รับการตอบกลับและบังคับใช้การตัดสินใจภายในการตอบสนอง
  • Policy Information Point (PIP) เป็นส่วนประกอบที่สามารถเชื่อมต่อ PDP กับแหล่งข้อมูลภายนอกเช่น LDAP ฐานข้อมูลหรือบริการบนเว็บ PIP มีประโยชน์เมื่อ PEP ส่งคำขอเช่น "Alice ดู doc # 12 ได้หรือไม่" และ PDP มีนโยบายที่กำหนดอายุของผู้ใช้ PDP จะถาม PIP "ให้อายุฉันแก่อลิซ" จากนั้นจะสามารถดำเนินการตามนโยบายได้
  • Policy Administration Point (PAP) เป็นสถานที่ที่คุณจัดการโซลูชัน XACML ทั้งหมด (การกำหนดแอตทริบิวต์การเขียนนโยบายและการกำหนดค่า PDP)

ภาษามาร์กอัปการควบคุมการเข้าถึง eXtensible - สถาปัตยกรรม XACML

กรณีการใช้งานครั้งแรกของคุณมีลักษณะดังนี้:

/*
 * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
 * 
 */
 policy departmentOne{
    target clause department == 1
    apply firstApplicable
    /**
     * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
     */
    rule allowFooBar1{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }

 }

กรณีการใช้งานครั้งที่สองของคุณจะเป็น:

 /*
  * "All users in department 2, if the date is after 03/15/2016, can VIEW resource FOOBAR-2, else not authorized"
  *  
  */
  policy departmentTwo{
    target clause department == 1
    apply firstApplicable
    rule allowFooBar2{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and currentDate>"2016/03/15":date and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }
  }

คุณสามารถรวมทั้งสองกรณีการใช้เป็นนโยบายเดียวโดยใช้การอ้างอิง:

  policyset global{
    apply firstApplicable
    departmentOne
    departmentTwo
  }

และคุณทำเสร็จแล้ว!

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ XACML และ ALFA ได้จาก:


0

สิ่งที่คุณต้องการที่นี่เป็นXACML มันสวยมากให้สิ่งที่คุณต้องการ คุณไม่จำเป็นต้องใช้สถาปัตยกรรมเต็มรูปแบบกับบทบาททั้งหมดที่ถูกแยกออกจากกันอย่างสมบูรณ์ ... หากคุณมีแอปพลิเคชั่นเพียงตัวเดียวคุณอาจหนีจากการรวม PDP และ PEP เข้ากับแอปของคุณด้วยbalanaและ PIP ฐานข้อมูลผู้ใช้ที่มีอยู่ของคุณคือ

ตอนนี้ที่ใดก็ได้ในแอปของคุณคุณต้องอนุญาตบางสิ่งคุณสร้างคำขอ XACML ซึ่งมีผู้ใช้การกระทำและบริบทและเครื่องมือ XACML จะทำการตัดสินใจตามไฟล์นโยบาย XACML ที่คุณเขียน ไฟล์นโยบายเหล่านี้สามารถเก็บไว้ในฐานข้อมูลหรือในระบบไฟล์หรือที่ใดก็ตามที่คุณต้องการเก็บการกำหนดค่า Axiomatics มีทางเลือกที่ดีในการเป็นตัวแทน XACML XML ชื่อ ALFA ที่อ่านง่ายกว่า raw raw เล็กน้อยและปลั๊กอิน Eclipse เพื่อสร้าง XACML XML จากนโยบาย ALFA


1
คำถามนี้ถามคำถามนี้อย่างไร
ริ้น

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

0

เราทำสิ่งนี้กับ บริษัท ปัจจุบันของฉันและเรามีความสุขมากกับผลลัพธ์

นิพจน์ของเราเขียนด้วย js และเรายังใช้เพื่อ จำกัด ผลลัพธ์ที่ผู้ใช้จะได้รับจากการสืบค้น ElasticSearch

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

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

ปรับปรุง:

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

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