JavaRush /จาวาบล็อก /Random-TH /JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1)
Viacheslav
ระดับ

JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1)

เผยแพร่ในกลุ่ม
การรักษาความปลอดภัยการเข้าถึงถูกนำมาใช้ใน Java มาเป็นเวลานานแล้ว และสถาปัตยกรรมสำหรับการรักษาความปลอดภัยนี้เรียกว่า JAAS - Java Authentication and Authorization Service การตรวจสอบนี้จะพยายามไขปริศนาว่าการรับรองความถูกต้อง การอนุญาตคืออะไร และ JAAS เกี่ยวข้องกับอะไร JAAS เป็นเพื่อนกับ Servlet API ได้อย่างไร และจุดที่พวกเขามีปัญหาในความสัมพันธ์
JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1) - 1

การแนะนำ

ในการทบทวนนี้ ฉันต้องการจะหารือเกี่ยวกับหัวข้อดังกล่าว เช่น ความปลอดภัยของแอปพลิเคชันบนเว็บ Java มีเทคโนโลยีหลายอย่างที่ให้ความปลอดภัย:
  • " สถาปัตยกรรมความปลอดภัยแพลตฟอร์ม Java SE " รายละเอียดเพิ่มเติมเกี่ยวกับสถาปัตยกรรมความปลอดภัยสามารถอ่านได้ในคำแนะนำจาก Oracle: " สถาปัตยกรรมความปลอดภัยแพลตฟอร์ม JavaTM SE " สถาปัตยกรรมนี้อธิบายวิธีที่เราต้องการรักษาความปลอดภัยแอปพลิเคชัน Java ของเราในสภาพแวดล้อมรันไทม์ Java SE แต่นี่ไม่ใช่หัวข้อสนทนาของเราในวันนี้

  • " Java Cryptography Architecture " เป็นส่วนขยาย Java ที่อธิบายการเข้ารหัสข้อมูล คุณสามารถอ่านเพิ่มเติมเกี่ยวกับส่วนขยายนี้บน JavaRush ได้ในรีวิว " Java Cryptography Architecture: First acquaintance " หรือในคำแนะนำจาก Oracle: " Java Cryptography Architecture (JCA) Reference Guide "

แต่การสนทนาของเราในวันนี้จะเกี่ยวกับเทคโนโลยีอื่นซึ่งเรียกว่า “Java Authentication and Authorization Service (JAAS)” เธอเป็นผู้อธิบายสิ่งสำคัญเช่นการรับรองความถูกต้องและการอนุญาต ลองดูรายละเอียดเพิ่มเติมนี้
JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1) - 2

จาส

JAASเป็นส่วนขยายของ Java SE และอธิบายไว้ในคู่มืออ้างอิง Java Authentication and Authorization Service (JAAS ) ตามชื่อของเทคโนโลยีที่แนะนำ JAAS อธิบายถึงวิธีการตรวจสอบสิทธิ์และการอนุญาตที่ควรดำเนินการ:
  • " Authentication ": แปลจากภาษากรีก "authentikos" แปลว่า "ของจริง ของแท้" นั่นคือการรับรองความถูกต้องคือการทดสอบความถูกต้อง ว่าใครก็ตามที่ได้รับการรับรองความถูกต้องคือคนที่พวกเขากล่าวว่าเป็นอย่างแท้จริง

  • " Authorization ": แปลจากภาษาอังกฤษแปลว่า "การอนุญาต" นั่นคือการอนุญาตคือการควบคุมการเข้าถึงที่ดำเนินการหลังจากการรับรองความถูกต้องสำเร็จ

นั่นคือ JAAS เป็นเรื่องเกี่ยวกับการกำหนดว่าใครกำลังร้องขอการเข้าถึงทรัพยากรและการตัดสินใจว่าเขาสามารถรับการเข้าถึงนี้ได้หรือไม่ การเปรียบเทียบเล็ก ๆ น้อย ๆ จากชีวิต:คุณกำลังขับรถไปตามถนนและผู้ตรวจสอบหยุดคุณ กรุณาเตรียมเอกสาร-ยืนยันตัวตน สามารถขับรถพร้อมเอกสาร-ใบอนุญาตได้ หรือเช่นคุณต้องการซื้อเครื่องดื่มแอลกอฮอล์ในร้านค้า ขั้นแรก ระบบจะขอให้คุณระบุหนังสือเดินทาง - การรับรองความถูกต้อง ถัดไป ขึ้นอยู่กับอายุของคุณ จะมีการตัดสินว่าคุณมีสิทธิ์ซื้อเครื่องดื่มแอลกอฮอล์หรือไม่ นี่คือการอนุญาต ในเว็บแอปพลิเคชัน การเข้าสู่ระบบในฐานะผู้ใช้ (ป้อนชื่อผู้ใช้และรหัสผ่าน) คือการตรวจสอบสิทธิ์ และการพิจารณาว่าหน้าใดที่คุณสามารถเปิดได้นั้นขึ้นอยู่กับการอนุญาต นี่คือจุดที่ “Java Authentication and Authorization Service (JAAS)” ช่วยเราได้ เมื่อพิจารณา JAAS สิ่งสำคัญคือต้องเข้าใจแนวคิดสำคัญหลายประการที่ JAAS อธิบาย: หัวข้อ อาจารย์ใหญ่ หนังสือรับรอง เรื่องเป็นเรื่องของการรับรองความถูกต้อง กล่าวคือเป็นผู้ถือหรือผู้ถือสิทธิ ในเอกสารประกอบ หัวเรื่อง ถูกกำหนดให้เป็นแหล่งที่มาของคำขอเพื่อดำเนินการบางอย่าง หัวเรื่องหรือแหล่งที่มาจะต้องอธิบายไว้ด้วยวิธีใดวิธีหนึ่ง และเพื่อจุดประสงค์นี้ มีการใช้ Principal ซึ่งในภาษารัสเซียบางครั้งเรียกว่า Principal นั่นคืออาจารย์ใหญ่แต่ละคนเป็นตัวแทนของหัวเรื่องจากมุมมองที่แน่นอน เพื่อให้ชัดเจนยิ่งขึ้น เรามายกตัวอย่าง: บุคคลหนึ่งเป็นหัวเรื่อง และผู้ต่อไปนี้สามารถทำหน้าที่เป็นอาจารย์ใหญ่ได้:
  • ใบขับขี่ของเขาเป็นตัวแทนของบุคคลในฐานะผู้ใช้ถนน
  • หนังสือเดินทางของเขาซึ่งเป็นตัวแทนของบุคคลในฐานะพลเมืองของประเทศของเขา
  • หนังสือเดินทางต่างประเทศของเขาเพื่อเป็นตัวแทนของบุคคลที่มีส่วนร่วมในความสัมพันธ์ระหว่างประเทศ
  • บัตรห้องสมุดของเขาในห้องสมุดเพื่อเป็นตัวแทนของบุคคลในฐานะผู้อ่านที่แนบมากับห้องสมุด
นอกจากนี้ Subject ยังมีชุด "ข้อมูลประจำตัว" ซึ่งหมายถึง "ตัวตน" ในภาษาอังกฤษ นี่คือวิธีที่ผู้ทดลองยืนยันว่าเขาเป็นเขา ตัวอย่างเช่น รหัสผ่านของผู้ใช้อาจเป็นข้อมูลประจำตัวได้ หรือวัตถุใด ๆ ที่ผู้ใช้สามารถยืนยันได้ว่าเขาคือเขาจริงๆ ตอนนี้เรามาดูกันว่า JAAS ถูกนำมาใช้ในเว็บแอปพลิเคชันอย่างไร
JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1) - 3

แอปพลิเคชันเว็บ

ดังนั้นเราจึงต้องมีเว็บแอปพลิเคชัน ระบบสร้างโปรเจ็กต์อัตโนมัติ Gradle จะช่วยเราสร้างมันขึ้นมา ขอบคุณการใช้ Gradle เราจึงสามารถดำเนินการคำสั่งเล็กๆ ประกอบโปรเจ็กต์ Java ในรูปแบบที่เราต้องการ สร้างโครงสร้างไดเร็กทอรีที่จำเป็นโดยอัตโนมัติ และอื่นๆ อีกมากมาย คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ Gradle ได้ในภาพรวมสั้นๆ: " A Brief Introduction to Gradle " หรือในเอกสารอย่างเป็นทางการ " Gradle Getting Started " เราจำเป็นต้องเริ่มต้นโปรเจ็กต์ (การเริ่มต้น) และเพื่อจุดประสงค์นี้ Gradle จึงมีปลั๊กอินพิเศษ: “ Gradle Init Plugin ” (Init ย่อมาจาก Initialization และง่ายต่อการจดจำ) หากต้องการใช้ปลั๊กอินนี้ ให้รันคำสั่งบนบรรทัดคำสั่ง:
gradle init --type java-application
หลังจากเสร็จสิ้นเราจะมีโปรเจ็กต์ Java ตอนนี้เรามาเปิดสคริปต์การสร้างโปรเจ็กต์ของเราเพื่อแก้ไขกัน สคริปต์บิลด์คือไฟล์ชื่อbuild.gradleซึ่งอธิบายความแตกต่างของบิลด์แอปพลิเคชัน จึงเป็นที่มาของชื่อ build script เราสามารถพูดได้ว่านี่คือสคริปต์สร้างโครงการ Gradle เป็นเครื่องมืออเนกประสงค์ที่ความสามารถพื้นฐานได้รับการขยายด้วยปลั๊กอิน ดังนั้นก่อนอื่น เรามาใส่ใจกับบล็อก "ปลั๊กอิน" กันก่อน:
plugins {
    id 'java'
    id 'application'
}
ตามค่าเริ่มต้น Gradle ตามที่เราระบุ " --type java-application" ได้ตั้งค่าชุดปลั๊กอินหลักบางตัวนั่นคือปลั๊กอินที่รวมอยู่ในการแจกจ่าย Gradle เอง หากคุณไปที่ส่วน "เอกสาร" (นั่นคือเอกสารประกอบ) บน เว็บไซต์ gradle.org ทางด้านซ้ายในรายการหัวข้อในส่วน "การอ้างอิง" เราจะเห็นส่วน " ปลั๊กอินหลัก " เช่น ส่วนที่มีคำอธิบายของปลั๊กอินพื้นฐานเหล่านี้ มาเลือกปลั๊กอินที่เราต้องการ ไม่ใช่ปลั๊กอินที่ Gradle สร้างขึ้นสำหรับเรา ตามเอกสารประกอบ " Gradle Java Plugin " ให้การดำเนินการพื้นฐานด้วยโค้ด Java เช่นการคอมไพล์ซอร์สโค้ด นอกจากนี้ ตามเอกสารประกอบ " ปลั๊กอินแอปพลิเคชัน Gradle " ให้เครื่องมือสำหรับการทำงานกับ "แอปพลิเคชัน JVM ที่ปฏิบัติการได้" เช่น ด้วยแอปพลิเคชัน Java ที่สามารถเปิดเป็นแอปพลิเคชันแบบสแตนด์อโลนได้ (เช่น แอปพลิเคชันคอนโซลหรือแอปพลิเคชันที่มี UI ของตัวเอง) ปรากฎว่าเราไม่ต้องการปลั๊กอิน “แอปพลิเคชัน” เพราะ... เราไม่จำเป็นต้องมีแอปแบบสแตนด์อโลน แต่เราต้องการเว็บแอป มาลบมันกันเถอะ เช่นเดียวกับการตั้งค่า “mainClassName” ซึ่งมีเพียงปลั๊กอินนี้เท่านั้นที่รู้จัก นอกจากนี้ ในส่วน " บรรจุภัณฑ์และการจัดจำหน่าย " เดียวกันซึ่งมีลิงก์ไปยังเอกสารประกอบของ Application Plugin มีลิงก์ไปยัง Gradle War Plugin Gradle War Pluginตามที่ระบุไว้ในเอกสารประกอบ ให้การสนับสนุนสำหรับการสร้างแอปพลิเคชันเว็บ Java ในรูปแบบ war ในรูปแบบ WAR หมายความว่าแทนที่จะเป็นไฟล์เก็บถาวร JAR ไฟล์เก็บถาวร WAR จะถูกสร้างขึ้น ดูเหมือนว่านี่คือสิ่งที่เราต้องการ นอกจากนี้ ตามเอกสารระบุว่า "ปลั๊กอิน The War ขยายปลั๊กอิน Java" นั่นคือเราสามารถแทนที่ปลั๊กอิน java ด้วยปลั๊กอิน war ได้ ดังนั้น บล็อกปลั๊กอินของเราจะมีลักษณะดังนี้:
plugins {
    id 'war'
}
นอกจากนี้ในเอกสารประกอบสำหรับ "ปลั๊กอิน Gradle War" มีการกล่าวว่าปลั๊กอินใช้ "เค้าโครงโครงการ" เพิ่มเติม เค้าโครงแปลจากภาษาอังกฤษเป็นสถานที่ตั้ง นั่นคือโดยค่าเริ่มต้นปลั๊กอิน war คาดว่าจะมีตำแหน่งไฟล์ที่แน่นอนที่จะใช้สำหรับงานของมัน โดยจะใช้ไดเร็กทอรีต่อไปนี้เพื่อจัดเก็บไฟล์แอปพลิเคชันเว็บ: src/main/webapp ลักษณะการทำงานของปลั๊กอินอธิบายไว้ดังนี้:
JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1) - 4
นั่นคือปลั๊กอินจะพิจารณาไฟล์จากตำแหน่งนี้เมื่อสร้างไฟล์เก็บถาวร WAR ของเว็บแอปพลิเคชันของเรา นอกจากนี้ เอกสาร Gradle War Plugin ระบุว่าไดเร็กทอรีนี้จะเป็น "รูทของไฟล์เก็บถาวร" และในนั้นเราสามารถสร้างไดเร็กทอรี WEB-INF และเพิ่มไฟล์ web.xml ที่นั่นได้ นี่เป็นไฟล์ประเภทใด? web.xml- นี่คือ "Deployment Descriptor" หรือ "deployment descriptor" นี่คือไฟล์ที่อธิบายวิธีกำหนดค่าเว็บแอปพลิเคชันของเราให้ทำงาน ไฟล์นี้ระบุคำขอที่แอปพลิเคชันของเราจะจัดการ การตั้งค่าความปลอดภัย และอื่นๆ อีกมากมาย ที่แกนกลาง มันค่อนข้างคล้ายกับไฟล์ Manifest จากไฟล์ JAR (ดู " การทำงานกับไฟล์ Manifest: พื้นฐาน ") ไฟล์ Manifest จะบอกวิธีการทำงานกับ Java Application (เช่น ไฟล์เก็บถาวร JAR) และ web.xml จะบอกวิธีการทำงานกับ Java Web Application (เช่น ไฟล์เก็บถาวร WAR) แนวคิดของ "Deployment Descriptor" ไม่ได้เกิดขึ้นเอง แต่อธิบายไว้ในเอกสาร " ข้อมูลจำเพาะของ Servlet API"" เว็บแอปพลิเคชัน Java ใด ๆ ขึ้นอยู่กับ "Servlet API" นี้ สิ่งสำคัญคือต้องเข้าใจว่านี่คือ API - นั่นคือเป็นคำอธิบายของสัญญาโต้ตอบบางอย่าง เว็บแอปพลิเคชันไม่ใช่แอปพลิเคชันอิสระ พวกเขาทำงานบนเว็บเซิร์ฟเวอร์ ซึ่งให้การสื่อสารผ่านเครือข่ายกับผู้ใช้ นั่นคือเว็บเซิร์ฟเวอร์เป็น "คอนเทนเนอร์" ชนิดหนึ่งสำหรับเว็บแอปพลิเคชัน นี่เป็นตรรกะเพราะเราต้องการเขียนตรรกะของเว็บแอปพลิเคชัน เช่น หน้าใดที่ผู้ใช้จะเห็นและอย่างไร พวกเขาควรตอบสนองต่อการกระทำของผู้ใช้และเราไม่ต้องการเขียนโค้ดเกี่ยวกับวิธีการส่งข้อความถึงผู้ใช้จำนวนไบต์ของข้อมูลที่จะถ่ายโอนและสิ่งอื่น ๆ ระดับต่ำและที่ต้องการคุณภาพมาก นอกจากนี้ ปรากฏว่าเว็บแอปพลิเคชันต่างกันหมดแต่การถ่ายโอนข้อมูลก็เหมือนกัน กล่าวคือ โปรแกรมเมอร์หลายล้านคนจะต้องเขียนโค้ดเพื่อจุดประสงค์เดียวกันซ้ำแล้วซ้ำเล่า ดังนั้น เว็บเซิร์ฟเวอร์จึงมีหน้าที่รับผิดชอบการโต้ตอบของผู้ใช้บางส่วน และการแลกเปลี่ยนข้อมูล และเว็บแอปพลิเคชันและนักพัฒนามีหน้าที่รับผิดชอบในการสร้างข้อมูลนั้น และเพื่อที่จะเชื่อมโยงสองส่วนนี้เข้าด้วยกันคือ เว็บเซิร์ฟเวอร์และเว็บแอปพลิเคชัน คุณต้องมีสัญญาสำหรับการโต้ตอบ เช่น พวกเขาจะปฏิบัติตามกฎอะไรในการทำเช่นนี้? เพื่ออธิบายสัญญาว่าการโต้ตอบระหว่างเว็บแอปพลิเคชันและเว็บเซิร์ฟเวอร์ควรมีลักษณะอย่างไร Servlet API จึงถูกประดิษฐ์ขึ้น สิ่งที่น่าสนใจคือ แม้ว่าคุณจะใช้เฟรมเวิร์กอย่าง Spring ก็ยังมี Servlet API ที่ทำงานอยู่เบื้องหลัง นั่นคือคุณใช้ Spring และ Spring ทำงานร่วมกับ Servlet API สำหรับคุณ ปรากฎว่าโครงการเว็บแอปพลิเคชันของเราต้องขึ้นอยู่กับ Servlet API ในกรณีนี้ Servlet API จะเป็นสิ่งอ้างอิง ดังที่เราทราบ Gradle ยังช่วยให้คุณสามารถอธิบายการพึ่งพาโครงการในลักษณะที่เปิดเผยได้ ปลั๊กอินอธิบายวิธีจัดการการพึ่งพา ตัวอย่างเช่น ปลั๊กอิน Java Gradle แนะนำวิธีการจัดการการพึ่งพา "testImplementation" ซึ่งบอกว่าการพึ่งพาดังกล่าวจำเป็นสำหรับการทดสอบเท่านั้น แต่ปลั๊กอิน Gradle War เพิ่มวิธีการจัดการการพึ่งพา "providedCompile" ซึ่งระบุว่าการพึ่งพาดังกล่าวจะไม่รวมอยู่ในไฟล์เก็บถาวร WAR ของเว็บแอปพลิเคชันของเรา เหตุใดเราจึงไม่รวม Servlet API ไว้ในไฟล์เก็บถาวร WAR ของเรา เนื่องจากเว็บเซิร์ฟเวอร์จะมอบ Servlet API ให้กับแอปพลิเคชันเว็บของเรา หากเว็บเซิร์ฟเวอร์จัดเตรียม Servlet API เซิร์ฟเวอร์นั้นจะเรียกว่าคอนเทนเนอร์เซิร์ฟเล็ต ดังนั้นจึงเป็นความรับผิดชอบของเว็บเซิร์ฟเวอร์ที่จะต้องจัดเตรียม Servlet API ให้กับเรา และเป็นความรับผิดชอบของเราที่จะต้องจัดเตรียม ServletAPI ในเวลาที่มีการคอมไพล์โค้ดเท่านั้น นั่นเป็นเหตุผลว่าprovidedCompileทำไม ดังนั้นบล็อกการขึ้นต่อกันจะมีลักษณะดังนี้:
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testImplementation 'junit:junit:4.12'
}
กลับไปที่ไฟล์ web.xml กัน ตามค่าเริ่มต้น Gradle จะไม่สร้าง Deployment Descriptor ใดๆ ขึ้นมา ดังนั้นเราจึงจำเป็นต้องสร้าง Deployment Descriptor ขึ้นมาเอง มาสร้างไดเร็กทอรีกันsrc/main/webapp/WEB-INFและในนั้นเราจะสร้างไฟล์ XML ชื่อweb.xml. ตอนนี้เรามาเปิด "Java Servlet Specification" และบท " CHAPTER 14 Deployment Descriptor " ตามที่ระบุไว้ใน "14.3 Deployment Descriptor" เอกสาร XML ของ Deployment Descriptor ได้รับการอธิบายโดยสคีมาhttp://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd สคีมา XML อธิบายว่าองค์ประกอบใดที่เอกสารสามารถประกอบด้วยได้ และควรปรากฏตามลำดับใด อันไหนบังคับ อันไหนไม่ใช่ โดยทั่วไปจะอธิบายโครงสร้างของเอกสารและช่วยให้คุณตรวจสอบว่าเอกสาร XML ได้รับการประกอบอย่างถูกต้องหรือไม่ ตอนนี้ลองใช้ตัวอย่างจากบท " 14.5 ตัวอย่าง " แต่ต้องระบุโครงร่างสำหรับเวอร์ชัน 3.1 เช่น
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
อันว่างของเราweb.xmlจะมีลักษณะดังนี้:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <display-name>JAAS Example</display-name>
</web-app>
ตอนนี้เรามาอธิบายเซิร์ฟเล็ตที่เราจะป้องกันโดยใช้ JAAS ก่อนหน้านี้ Gradle ได้สร้างคลาส App ให้เรา มาเปลี่ยนเป็นเซิร์ฟเล็ตกันดีกว่า ตามที่ระบุไว้ในข้อกำหนดใน " บทที่ 2 อินเทอร์เฟซของเซิร์ฟเล็ต " ว่า " สำหรับวัตถุประสงค์ส่วนใหญ่ นักพัฒนาจะขยาย HttpServlet เพื่อใช้งานเซิร์ฟเล็ตของตน " นั่นคือ เพื่อสร้างคลาสให้เป็นเซิร์ฟเล็ต คุณต้องสืบทอดคลาสนี้จากHttpServlet:
public class App extends HttpServlet {
	public String getGreeting() {
        return "Secret!";
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().print(getGreeting());
    }
}
ดังที่เราได้กล่าวไปแล้ว Servlet API เป็นสัญญาระหว่างเซิร์ฟเวอร์และเว็บแอปพลิเคชันของเรา สัญญานี้ช่วยให้เราอธิบายว่าเมื่อผู้ใช้ติดต่อกับเซิร์ฟเวอร์ เซิร์ฟเวอร์จะสร้างคำขอจากผู้ใช้ในรูปแบบของออบเจ็กต์HttpServletRequestและส่งผ่านไปยังเซิร์ฟเล็ต นอกจากนี้ยังจัดเตรียมอ็อบเจ็กต์ให้กับเซิร์ฟเล็ตด้วยHttpServletResponseเพื่อให้เซิร์ฟเล็ตสามารถเขียนการตอบกลับให้กับผู้ใช้ได้ เมื่อเซิร์ฟเล็ตทำงานเสร็จแล้ว เซิร์ฟเวอร์จะสามารถให้คำตอบแก่ผู้ใช้ตามHttpServletResponseนั้น นั่นคือเซิร์ฟเล็ตไม่ได้สื่อสารกับผู้ใช้โดยตรง แต่สื่อสารกับเซิร์ฟเวอร์เท่านั้น เพื่อให้เซิร์ฟเวอร์รู้ว่าเรามีเซิร์ฟเล็ตและจำเป็นต้องใช้คำขอใด เราต้องแจ้งให้เซิร์ฟเวอร์ทราบเกี่ยวกับสิ่งนี้ในตัวอธิบายการปรับใช้:
<servlet>
	<servlet-name>app</servlet-name>
	<servlet-class>jaas.App</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>app</servlet-name>
	<url-pattern>/secret</url-pattern>
</servlet-mapping>
ในกรณีนี้ คำขอทั้งหมด จะ ไม่/secretถูกส่งไปยังเซิร์ฟเล็ตเดียวของเราตามชื่อappซึ่งสอดคล้องกับคลาส jaas.Appดังที่เราได้กล่าวไว้ก่อนหน้านี้ เว็บแอปพลิเคชันสามารถใช้งานได้บนเว็บเซิร์ฟเวอร์เท่านั้น เว็บเซิร์ฟเวอร์สามารถติดตั้งแยกต่างหาก (สแตนด์อโลน) แต่สำหรับวัตถุประสงค์ของการตรวจสอบนี้ ตัวเลือกอื่นก็เหมาะสม - ทำงานบนเซิร์ฟเวอร์แบบฝัง ซึ่งหมายความว่าเซิร์ฟเวอร์จะถูกสร้างขึ้นและเปิดใช้งานโดยทางโปรแกรม (ปลั๊กอินจะดำเนินการนี้ให้เรา) และในขณะเดียวกันเว็บแอปพลิเคชันของเราก็จะถูกปรับใช้บนเซิร์ฟเวอร์นั้น ระบบการสร้าง Gradle อนุญาตให้คุณใช้ปลั๊กอิน " Gradle Gretty Plugin " เพื่อวัตถุประสงค์เหล่านี้:
plugins {
    id 'war'
    id 'org.gretty' version '2.2.0'
}
นอกจากนี้ ปลั๊กอิน Gretty ยังมีเอกสารประกอบ ที่ดีอีก ด้วย เริ่มต้นด้วยความจริงที่ว่าปลั๊กอิน Gretty ช่วยให้คุณสามารถสลับระหว่างเว็บเซิร์ฟเวอร์ต่างๆ มีการอธิบายรายละเอียดเพิ่มเติมในเอกสารประกอบ: " การสลับระหว่างคอนเทนเนอร์เซิร์ฟเล็ต " มาเปลี่ยนมาใช้ Tomcat กันดีกว่า เพราะ... เป็นหนึ่งในความนิยมในการใช้งานมากที่สุด และยังมีเอกสารที่ดีและตัวอย่างและการวิเคราะห์ปัญหามากมาย:
gretty {
    // Переключаемся с дефолтного Jetty на Tomcat
    servletContainer = 'tomcat8'
    // Укажем Context Path, он же Context Root
    contextPath = '/jaas'
}
ตอนนี้เราสามารถรัน "gradle appRun" ได้แล้ว จากนั้นเว็บแอปพลิเคชันของเราจะพร้อมใช้งานที่ http://localhost:8080/jaas/secret
JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1) - 5
สิ่งสำคัญคือต้องตรวจสอบว่า Tomcat เลือกคอนเทนเนอร์เซิร์ฟเล็ต (ดู #1) และตรวจสอบว่าเว็บแอปพลิเคชันของเรามีอยู่ที่ที่อยู่ใด (ดู #2)
JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1) - 6

การรับรองความถูกต้อง

การตั้งค่าการรับรองความถูกต้องมักประกอบด้วยสองส่วน: การตั้งค่าบนฝั่งเซิร์ฟเวอร์และการตั้งค่าที่ด้านข้างของแอปพลิเคชันเว็บที่ทำงานบนเซิร์ฟเวอร์นี้ การตั้งค่าความปลอดภัยของเว็บแอปพลิเคชันไม่สามารถโต้ตอบกับการตั้งค่าความปลอดภัยของเว็บเซิร์ฟเวอร์ได้ หากไม่มีเหตุผลอื่นนอกเหนือจากนั้น เว็บแอปพลิเคชันไม่สามารถโต้ตอบกับเว็บเซิร์ฟเวอร์ได้ ไม่ใช่เรื่องไร้ประโยชน์ที่เราเปลี่ยนมาใช้ Tomcat เพราะ... Tomcat มีสถาปัตยกรรมที่มีการอธิบายไว้อย่างดี (ดู " สถาปัตยกรรม Apache Tomcat 8 ") จากคำอธิบายของสถาปัตยกรรมนี้ เป็นที่ชัดเจนว่า Tomcat ซึ่งเป็นเว็บเซิร์ฟเวอร์ แสดงถึงเว็บแอปพลิเคชันเป็นบริบทบางอย่าง ซึ่งเรียกว่า " บริบท Tomcat " บริบทนี้ทำให้แต่ละแอปพลิเคชันเว็บมีการตั้งค่าของตัวเอง โดยแยกออกจากแอปพลิเคชันเว็บอื่นๆ นอกจากนี้ แอปพลิเคชันบนเว็บสามารถส่งผลต่อการตั้งค่าของบริบทนี้ได้ มีความยืดหยุ่นและสะดวกสบาย เพื่อความเข้าใจที่ลึกซึ้งยิ่งขึ้น เราขอแนะนำให้อ่านบทความ " การทำความเข้าใจ Tomcat Context Containers " และส่วนเอกสารประกอบ Tomcat " The Context Container " ตามที่ระบุไว้ข้างต้น เว็บแอปพลิเคชันของเราสามารถมีอิทธิพลต่อบริบท Tomcat ของแอปพลิเคชันของเราได้โดยใช้/META-INF/context.xml. และหนึ่งในการตั้งค่าที่สำคัญมากที่เราสามารถมีอิทธิพลต่อได้คือขอบเขตความปลอดภัย ขอบเขตความปลอดภัยเป็น "พื้นที่รักษาความปลอดภัย" ประเภทหนึ่ง พื้นที่ที่มีการระบุการตั้งค่าความปลอดภัยเฉพาะ ดังนั้น เมื่อใช้ขอบเขตความปลอดภัย เราจะใช้การตั้งค่าความปลอดภัยที่กำหนดไว้สำหรับขอบเขตนี้ ขอบเขตความปลอดภัยได้รับการจัดการโดยคอนเทนเนอร์ เช่น เว็บเซิร์ฟเวอร์ ไม่ใช่เว็บแอปพลิเคชันของเรา เราสามารถบอกเซิร์ฟเวอร์ได้เฉพาะว่าขอบเขตการรักษาความปลอดภัยใดที่ต้องขยายไปยังแอปพลิเคชันของเรา เอกสาร Tomcat ในส่วน " The Realm Component " อธิบาย Realm ว่าเป็นชุดข้อมูลเกี่ยวกับผู้ใช้และบทบาทในการดำเนินการตรวจสอบสิทธิ์ Tomcat จัดเตรียมชุดการใช้งาน Security Realm ที่แตกต่างกัน หนึ่งในนั้นคือ " Jaas Realm " เมื่อเข้าใจคำศัพท์เพียงเล็กน้อยแล้ว เรามาอธิบายบริบทของ Tomcat ในไฟล์กันดีกว่า/META-INF/context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Realm className="org.apache.catalina.realm.JAASRealm"
           appName="JaasLogin"
           userClassNames="jaas.login.UserPrincipal"
           roleClassNames="jaas.login.RolePrincipal"
           configFile="jaas.config" />
</Context>
appName— ชื่อแอปพลิเคชัน Tomcat จะพยายามจับคู่ชื่อนี้กับชื่อที่ระบุในไฟล์configFile. configFile- นี่คือ "ไฟล์การกำหนดค่าการเข้าสู่ระบบ" ตัวอย่างนี้สามารถดูได้ในเอกสารประกอบของ JAAS: " ภาคผนวก B: ตัวอย่างการกำหนดค่าการเข้าสู่ระบบ " นอกจากนี้ สิ่งสำคัญคือต้องค้นหาไฟล์นี้ในทรัพยากรก่อน ดังนั้นเว็บแอปพลิเคชันของเราจึงสามารถจัดเตรียมไฟล์นี้ได้เอง คุณลักษณะuserClassNamesและroleClassNamesมีการบ่งชี้ของคลาสที่เป็นตัวแทนของหลักการของผู้ใช้ JAAS แยกแนวคิดของ "ผู้ใช้" และ "บทบาท" ออกเป็นสองแนวคิดที่แตกต่างjava.security.Principalกัน เรามาอธิบายคลาสข้างต้นกันดีกว่า มาสร้างการใช้งานที่ง่ายที่สุดสำหรับหลักการผู้ใช้:
public class UserPrincipal implements Principal {
    private String name;
    public UserPrincipal(String name) {
        this.name = name;
    }
    @Override
    public String getName() {
        return name;
    }
}
เราจะดำเนินการแบบเดียวกันนี้ซ้ำทุกประการRolePrincipalสำหรับ ดังที่คุณเห็นจากอินเทอร์เฟซ สิ่งสำคัญสำหรับ Principal คือการจัดเก็บและส่งกลับชื่อ (หรือ ID) ที่แสดงถึง Principal ตอนนี้ เรามีขอบเขตความปลอดภัย เรามีคลาสหลัก ยังคงต้องเติมไฟล์จากconfigFileแอตทริบิวต์ " " หรือที่เรียกlogin configuration fileว่า คำอธิบายสามารถพบได้ในเอกสาร Tomcat: " The Realm Component "
JAAS - เทคโนโลยีเบื้องต้น (ตอนที่ 1) - 7
นั่นคือ เราสามารถวางการตั้งค่า JAAS Login Config ไว้ในทรัพยากรของเว็บแอปพลิเคชันของเราได้ และต้องขอบคุณ Tomcat Context ที่ทำให้เราสามารถใช้งานได้ ไฟล์นี้จะต้องสามารถใช้เป็นทรัพยากรสำหรับ ClassLoader ได้ ดังนั้นพาธของไฟล์จึงควรเป็นดังนี้: \src\main\resources\jaas.config มาตั้งค่าเนื้อหาของไฟล์นี้กัน:
JaasLogin {
    jaas.login.JaasLoginModule required debug=true;
};
เป็นที่น่าสังเกตว่าcontext.xmlมีการใช้ชื่อเดียวกันที่นี่และใน ซึ่งจะแมปขอบเขตความปลอดภัยกับ LoginModule ดังนั้น Tomcat Context บอกเราว่าคลาสใดเป็นตัวแทนของหลักการ รวมถึง LoginModule ใดที่จะใช้ สิ่งที่เราต้องทำคือใช้ LoginModule นี้ LoginModuleอาจเป็นหนึ่งในสิ่งที่น่าสนใจที่สุดใน JAAS เอกสารอย่างเป็นทางการจะช่วยเราในการพัฒนา LoginModule: " Java Authentication and Authorization Service (JAAS): LoginModule Developer's Guide " ลองใช้โมดูลการเข้าสู่ระบบ มาสร้างคลาสที่ใช้อินเทอร์เฟซLoginModule:
public class JaasLoginModule implements LoginModule {
}
ก่อนอื่นเราจะอธิบายวิธีการเริ่มต้นLoginModule:
private CallbackHandler handler;
private Subject subject;
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, <String, ?> sharedState, Map<String, ?> options) {
	handler = callbackHandler;
	this.subject = subject;
}
วิธีนี้จะบันทึกSubjectซึ่งเราจะตรวจสอบเพิ่มเติมและกรอกข้อมูลเกี่ยวกับตัวการ เราจะบันทึกไว้เพื่อใช้ในอนาคตCallbackHandlerซึ่งมอบให้กับเรา ด้วยความช่วยเหลือCallbackHandlerเราสามารถขอข้อมูลต่างๆ เกี่ยวกับเรื่องการรับรองความถูกต้องได้ในภายหลัง คุณสามารถอ่าน เพิ่มเติมได้CallbackHandlerในส่วนที่เกี่ยวข้องของเอกสารประกอบ: " คู่มืออ้างอิง JAAS: CallbackHandler " จากนั้นจึงดำเนินการวิธีloginการรับรองความถูกSubjectต้อง นี่เป็นขั้นตอนแรกของการรับรองความถูกต้อง:
@Override
public boolean login() throws LoginException {
	// Добавляем колбэки
	Callback[] callbacks = new Callback[2];
	callbacks[0] = new NameCallback("login");
	callbacks[1] = new PasswordCallback("password", true);
	// При помощи колбэков получаем через CallbackHandler логин и пароль
	try {
		handler.handle(callbacks);
		String name = ((NameCallback) callbacks[0]).getName();
		String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());
		// Далее выполняем валидацию.
		// Тут просто для примера проверяем определённые значения
		if (name != null && name.equals("user123") && password != null && password.equals("pass123")) {
			// Сохраняем информацию, которая будет использована в методе commit
			// Не "пачкаем" Subject, т.к. не факт, что commit выполнится
			// Для примера проставим группы вручную, "хардcodeно".
			login = name;
			userGroups = new ArrayList<String>();
			userGroups.add("admin");
			return true;
		} else {
			throw new LoginException("Authentication failed");
		}
	} catch (IOException | UnsupportedCallbackException e) {
		throw new LoginException(e.getMessage());
	}
}
เป็นสิ่งสำคัญที่loginเราไม่ควรเปลี่ยนSubject. commitการ เปลี่ยนแปลงดังกล่าวควรเกิดขึ้นในวิธีการยืนยันเท่านั้น ต่อไป เราต้องอธิบายวิธีการยืนยันการรับรองความถูกต้องที่สำเร็จ:
@Override
public boolean commit() throws LoginException {
	userPrincipal = new UserPrincipal(login);
	subject.getPrincipals().add(userPrincipal);
	if (userGroups != null && userGroups.size() > 0) {
		for (String groupName : userGroups) {
			rolePrincipal = new RolePrincipal(groupName);
			subject.getPrincipals().add(rolePrincipal);
		}
	}
	return true;
}
อาจดูแปลกที่จะแยกวิธีการloginและcommit. แต่ประเด็นก็คือสามารถรวมโมดูลการเข้าสู่ระบบเข้าด้วยกันได้ และเพื่อให้การรับรองความถูกต้องประสบความสำเร็จ อาจจำเป็นที่โมดูลการเข้าสู่ระบบหลายโมดูลจะทำงานได้สำเร็จ และเฉพาะในกรณีที่โมดูลที่จำเป็นทั้งหมดใช้งานได้แล้ว ให้บันทึกการเปลี่ยนแปลง นี่คือขั้นตอนที่สองของการรับรองความถูกต้อง มาจบกันด้วย วิธีการ abortและlogout:
@Override
public boolean abort() throws LoginException {
	return false;
}
@Override
public boolean logout() throws LoginException {
	subject.getPrincipals().remove(userPrincipal);
	subject.getPrincipals().remove(rolePrincipal);
	return true;
}
วิธีการนี้abortจะถูกเรียกเมื่อขั้นตอนแรกของการรับรองความถูกต้องล้มเหลว วิธีการนี้logoutจะถูกเรียกเมื่อระบบออกจากระบบ เมื่อใช้งานของเราLogin Moduleและกำหนดค่าแล้วSecurity Realmตอนนี้เราต้องระบุweb.xmlความจริงที่ว่าเราต้องการใช้อันใดอันหนึ่งLogin Config:
<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>JaasLogin</realm-name>
</login-config>
เราระบุชื่อของขอบเขตความปลอดภัยของเราและระบุวิธีการรับรองความถูกต้อง - พื้นฐาน นี่คือหนึ่งในประเภทของการรับรองความถูกต้องที่อธิบายไว้ใน Servlet API ในส่วน " 13.6 การรับรองความถูกต้อง " ยังคงอยู่
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION