JavaRush /בלוג Java /Random-HE /JAAS - מבוא לטכנולוגיה (חלק 1)
Viacheslav
רָמָה

JAAS - מבוא לטכנולוגיה (חלק 1)

פורסם בקבוצה
אבטחת גישה מיושמת ב-Java כבר די הרבה זמן והארכיטקטורה למתן אבטחה זו נקראת JAAS - Java Authentication and Authorization Service. סקירה זו תנסה לפענח את התעלומה של מהי אימות, הרשאה ומה הקשר ל-JAAS. איך JAAS חבר עם ה-API של Servlet, והיכן יש להם בעיות במערכת היחסים שלהם.
JAAS - מבוא לטכנולוגיה (חלק 1) - 1

מבוא

בסקירה זו ברצוני לדון בנושא כמו אבטחת יישומי אינטרנט. ל-Java יש מספר טכנולוגיות המספקות אבטחה: אבל השיחה שלנו היום תהיה על טכנולוגיה אחרת, שנקראת "שירות אימות והרשאות ג'אווה (JAAS)". היא זו שמתארת ​​דברים חשובים כמו אימות והרשאה. בואו נסתכל על זה ביתר פירוט.
JAAS - מבוא לטכנולוגיה (חלק 1) - 2

JAAS

JAAS היא הרחבה ל-Java SE ומתוארת במדריך העזר של Java Authentication and Authorization Service (JAAS) . כפי שמרמז שם הטכנולוגיה, JAAS מתאר כיצד יש לבצע אימות והרשאה:
  • " אימות ": בתרגום מיוונית, "authentikos" פירושו "אמיתי, אמיתי". כלומר, אימות הוא מבחן לאותנטיות. שמי שמאומת הוא באמת מי שהם אומרים שהוא.

  • " הרשאה ": בתרגום מאנגלית פירושו "הרשאה". כלומר, הרשאה היא בקרת גישה המבוצעת לאחר אימות מוצלח.

כלומר, JAAS עוסק בקביעה מי מבקש גישה למשאב וקבלת החלטה האם הוא יכול לקבל גישה זו. אנלוגיה קטנה מהחיים: אתה נוסע בכביש ופקח עוצר אותך. נא לספק מסמכים - אימות. האם אתה יכול לנהוג במכונית עם מסמכים - אישור. או, למשל, אתה רוצה לקנות אלכוהול בחנות. ראשית, מבקשים ממך דרכון - אימות. לאחר מכן, בהתאם לגילכם, מחליטים האם אתם זכאים לקנות אלכוהול. זו הרשאה. ביישומי אינטרנט, כניסה כמשתמש (הזנת שם משתמש וסיסמה) היא אימות. והקביעה אילו דפים אתה יכול לפתוח נקבעת על פי אישור. זה המקום שבו "שירות האימות וההרשאות של Java (JAAS)" עוזר לנו. כאשר בוחנים JAAS, חשוב להבין כמה מושגי מפתח שמתארים JAAS: נושא, מנהלים, אישורים. הנושא הוא נושא האימות. כלומר, הוא הנושא או בעל הזכויות. בתיעוד, Subject מוגדר כמקור של בקשה לבצע פעולה כלשהי. יש לתאר איכשהו את הנושא או המקור ולצורך כך משתמשים ב- Principal, שברוסית מכונה לפעמים גם Principal. כלומר, כל מנהל הוא ייצוג של סובייקט מנקודת מבט מסוימת. כדי להבהיר את זה, בואו ניתן דוגמה: אדם מסוים הוא סובייקט. והבאים יכולים לשמש כמנהלים:
  • רישיון הנהיגה שלו כייצוג של אדם כמשתמש בדרך
  • הדרכון שלו, כייצוג של אדם כאזרח במדינתו
  • דרכונו הזר, כייצוג של אדם כמשתתף ביחסים בינלאומיים
  • כרטיס הספרייה שלו בספרייה, כייצוג של אדם כקורא המוצמד לספרייה
בנוסף, לנושא יש קבוצה של "אישורים", שפירושו "זהות" באנגלית. כך הנבדק מאשר שהוא הוא. לדוגמה, הסיסמה של המשתמש יכולה להיות האישור. או כל חפץ שבעזרתו המשתמש יכול לאשר שהוא באמת הוא. כעת נראה כיצד JAAS משמש ביישומי אינטרנט.
JAAS - מבוא לטכנולוגיה (חלק 1) - 3

אפליקציית רשת

אז, אנחנו צריכים יישום אינטרנט. מערכת בניית הפרויקט האוטומטית של Gradle תעזור לנו ליצור אותה. הודות לשימוש ב- Gradle, אנו יכולים, על ידי ביצוע פקודות קטנות, להרכיב פרויקט Java בפורמט שאנו צריכים, ליצור באופן אוטומטי את מבנה הספריות הדרוש ועוד ועוד. אתה יכול לקרוא עוד על Gradle בסקירה הקצרה: " מבוא קצר ל- Gradle " או בתיעוד הרשמי " Gradle Getting Started ". אנחנו צריכים לאתחל את הפרויקט (אתחול), ולצורך זה יש ל-Gradle תוסף מיוחד: " Gradle Init Plugin " (Init הוא קיצור של Initialization, קל לזכור). כדי להשתמש בתוסף זה, הפעל את הפקודה בשורת הפקודה:
gradle init --type java-application
לאחר סיום מוצלח, יהיה לנו פרויקט Java. בואו נפתח כעת את סקריפט הבנייה של הפרויקט שלנו לעריכה. סקריפט בנייה הוא קובץ בשם build.gradle, שמתאר את הניואנסים של בניית היישום. מכאן השם, בניית תסריט. אנו יכולים לומר שזהו סקריפט לבניית פרויקט. Gradle הוא כלי כה רב תכליתי, שהיכולות הבסיסיות שלו מורחבות באמצעות תוספים. לכן, קודם כל, בואו נשים לב לבלוק "תוספים":
plugins {
    id 'java'
    id 'application'
}
כברירת מחדל, Gradle, בהתאם למה שציינו " --type java-application", הקימה קבוצה של כמה תוספים ליבה, כלומר אותם תוספים שנכללים בהפצה של Gradle עצמה. אם אתה עובר לקטע "מסמכים" (כלומר, תיעוד) באתר gradle.org , אז בצד שמאל ברשימת הנושאים בסעיף "הפניה" אנו רואים את הסעיף " תוספי ליבה ", כלומר. קטע עם תיאור של התוספים הבסיסיים האלה. בוא נבחר בדיוק את התוספים שאנחנו צריכים, ולא את אלה ש-Gradle יצר עבורנו. על פי התיעוד, " פלאגין ג'אווה Gradle " מספק פעולות בסיסיות עם קוד Java, כגון הידור קוד מקור. כמו כן, על פי התיעוד, " תוסף אפליקציית Gradle " מספק לנו כלים לעבודה עם "יישום JVM להפעלה", כלומר. עם אפליקציית java שניתן להפעיל כאפליקציה עצמאית (לדוגמה, אפליקציית קונסולה או אפליקציה עם ממשק משתמש משלה). מסתבר שאנחנו לא צריכים את התוסף "אפליקציה", כי... אנחנו לא צריכים אפליקציה עצמאית, אנחנו צריכים אפליקציית אינטרנט. בואו נמחק את זה. כמו גם ההגדרה "mainClassName", המוכרת רק לפלאגין הזה. יתרה מזאת, באותו קטע " אריזה והפצה " שבו סופק הקישור לתיעוד תוסף האפליקציה, יש קישור לתוסף מלחמת Gradle. Gradle War Plugin , כפי שמצוין בתיעוד, מספק תמיכה ליצירת יישומי אינטרנט של Java בפורמט מלחמה. בפורמט WAR פירושו שבמקום ארכיון JAR, ייווצר ארכיון WAR. נראה שזה מה שאנחנו צריכים. כמו כן, כפי שאומר התיעוד, "תוסף המלחמה מרחיב את תוסף ג'אווה". כלומר, אנחנו יכולים להחליף את תוסף ה-Java בתוסף המלחמה. לכן, בלוק הפלאגין שלנו ייראה בסופו של דבר כך:
plugins {
    id 'war'
}
גם בתיעוד של "תוסף מלחמת גראדל" נאמר שהתוסף משתמש ב"פריסת פרויקט" נוספת. פריסה מתורגמת מאנגלית כמיקום. כלומר, תוסף המלחמה כברירת מחדל מצפה לקיומו של מיקום מסוים של קבצים שהוא ישתמש במשימותיו. הוא ישתמש בספרייה הבאה כדי לאחסן קבצי אפליקציות אינטרנט: src/main/webapp התנהגות התוסף מתוארת באופן הבא:
JAAS - מבוא לטכנולוגיה (חלק 1) - 4
כלומר, התוסף ייקח בחשבון קבצים ממיקום זה בעת בניית ארכיון ה-WAR של אפליקציית האינטרנט שלנו. בנוסף, התיעוד של Gradle War Plugin אומר שהספרייה הזו תהיה "שורש הארכיון". וכבר בה נוכל ליצור ספריית WEB-INF ולהוסיף שם את הקובץ web.xml. איזה סוג קובץ זה? web.xml- זהו "מתאר פריסה" או "מתאר פריסה". זהו קובץ שמתאר כיצד להגדיר את יישום האינטרנט שלנו כך שיעבוד. קובץ זה מפרט באילו בקשות האפליקציה שלנו תטפל, הגדרות אבטחה ועוד הרבה יותר. בבסיסו, הוא דומה במקצת לקובץ מניפסט מקובץ JAR (ראה " עבודה עם קובצי מניפסט: היסודות "). קובץ המניפסט אומר כיצד לעבוד עם יישום Java (כלומר ארכיון JAR), וה-web.xml מספר כיצד לעבוד עם יישום אינטרנט של Java (כלומר ארכיון WAR). עצם המושג "Deployment Descriptor" לא עלה בפני עצמו, אלא מתואר במסמך " Servlet API Specification"". כל אפליקציית אינטרנט של Java תלויה ב-"Servlet API" הזה. חשוב להבין שמדובר ב-API - כלומר, זה תיאור של חוזה אינטראקציה כלשהו. אפליקציות אינטרנט אינן אפליקציות עצמאיות. הן פועלות על שרת אינטרנט. , המספק תקשורת רשת עם משתמשים. כלומר, שרת אינטרנט הוא מעין "מיכל" עבור יישומי אינטרנט. זה הגיוני, כי אנחנו רוצים לכתוב את ההיגיון של אפליקציית אינטרנט, כלומר אילו דפים המשתמש יראה וכיצד הם צריכים להגיב לפעולות של המשתמש. ואנחנו לא רוצים לכתוב קוד איך הודעה תישלח למשתמש, איך יועבר בתים של מידע ועוד דברים ברמה נמוכה ומאוד דורשת איכות. בנוסף, מסתבר שיישומי אינטרנט שונים כולם, אבל העברת הנתונים זהה. כלומר, מיליון מתכנתים יצטרכו לכתוב קוד לאותה מטרה שוב ושוב. אז שרת האינטרנט אחראי על חלק מהאינטראקציה של המשתמשים וחילופי נתונים, ויישום האינטרנט והמפתח אחראים להפקת הנתונים הללו. ועל מנת לחבר את שני החלקים הללו, דהיינו. שרת אינטרנט ויישום אינטרנט, אתה צריך חוזה עבור האינטראקציה שלהם, כלומר. אילו כללים הם יפעלו כדי לעשות זאת? כדי לתאר איכשהו את החוזה, איך צריכה להיראות האינטראקציה בין יישום אינטרנט לשרת אינטרנט, הומצא ה-API של Servlet. מעניין, גם אם אתה משתמש במסגרות כמו Spring, עדיין יש Servlet API שרץ מתחת למכסה המנוע. כלומר, אתה משתמש ב-Spring, ו-Spring עובד עם ה-API של Servlet בשבילך. מסתבר שפרויקט יישומי האינטרנט שלנו חייב להיות תלוי ב- Servlet API. במקרה זה, ה-API של Servlet יהיה תלות. כידוע, Gradle גם מאפשר לך לתאר תלות בפרויקט בצורה הצהרתית. תוספים מתארים כיצד ניתן לנהל תלות. לדוגמה, תוסף Java Gradle מציג שיטת ניהול תלות "testImplementation", האומרת שתלות כזו נחוצה רק לבדיקות. אבל התוסף Gradle War מוסיף שיטת ניהול תלות "providedCompile", האומרת שתלות כזו לא תיכלל בארכיון WAR של אפליקציית האינטרנט שלנו. מדוע לא נכלול את ה-API של Servlet בארכיון ה-WAR שלנו? מכיוון שה-API של Servlet יסופק לאפליקציית האינטרנט שלנו על ידי שרת האינטרנט עצמו. אם שרת אינטרנט מספק Servlet API, אז השרת נקרא מיכל servlet. לכן, באחריות שרת האינטרנט לספק לנו את ה-API של Servlet, ובאחריותנו לספק את ה-ServletAPI רק בזמן הקומפילציה של הקוד. בגלל זה providedCompile. לפיכך, בלוק התלות ייראה כך:
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testImplementation 'junit:junit:4.12'
}
אז בואו נחזור לקובץ web.xml. כברירת מחדל, Gradle לא יוצר שום מתאר פריסה, אז אנחנו צריכים לעשות זאת בעצמנו. בואו ניצור ספרייה src/main/webapp/WEB-INF, ובה ניצור קובץ XML בשם web.xml. כעת בואו נפתח את "מפרט Java Servlet" עצמו ואת הפרק " פרק 14 מתאר פריסה ". כפי שצוין ב-"14.3 Descriptor 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 יצר עבורנו את כיתת האפליקציה. בואו נהפוך את זה לסרבלט. כפי שצוין במפרט ב"פרק 2 ממשק ה-servlet ", ש"לרוב המטרות, מפתחים ירחיבו את HttpServlet כדי ליישם את ה-servlets שלהם ", כלומר, כדי להפוך מחלקה ל-servlet, אתה צריך לרשת את המחלקה הזו מ 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());
    }
}
כפי שאמרנו, ה-API של Servlet הוא חוזה בין השרת לאפליקציית האינטרנט שלנו. חוזה זה מאפשר לנו לתאר שכאשר משתמש יוצר קשר עם השרת, השרת יפיק בקשה מהמשתמש בצורת אובייקט HttpServletRequestויעביר אותה ל-servlet. זה גם יספק ל-servlet אובייקט HttpServletResponseכך שה-servlet יוכל לכתוב לו תגובה עבור המשתמש. לאחר שה-servlet סיים לפעול, השרת יוכל לספק למשתמש תגובה המבוססת על זה HttpServletResponse. כלומר, ה-servlet אינו מתקשר ישירות עם המשתמש, אלא רק עם השרת. על מנת שהשרת יידע שיש לנו servlet ולאילו בקשות יש להשתמש בו, עלינו לספר לשרת על כך במתאר הפריסה:
<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 מאפשר לך לעבור בין שרתי אינטרנט שונים. זה מתואר ביתר פירוט בתיעוד: " מעבר בין מיכלי servlet ". בואו נעבור לטומקט, כי... הוא אחד הפופולריים ביותר בשימוש, ויש לו גם תיעוד טוב והרבה דוגמאות ובעיות מנותחות:
gretty {
    // Переключаемся с дефолтного Jetty на Tomcat
    servletContainer = 'tomcat8'
    // Укажем Context Path, он же Context Root
    contextPath = '/jaas'
}
כעת נוכל להפעיל "gradle appRun" ואז אפליקציית האינטרנט שלנו תהיה זמינה בכתובת http://localhost:8080/jaas/secret
JAAS - מבוא לטכנולוגיה (חלק 1) - 5
חשוב לבדוק שמיכל ה-servlet נבחר על ידי Tomcat (ראה מס' 1) ולבדוק באיזו כתובת זמינה אפליקציית האינטרנט שלנו (ראה מס' 2).
JAAS - מבוא לטכנולוגיה (חלק 1) - 6

אימות

הגדרות אימות מורכבות לרוב משני חלקים: הגדרות בצד השרת והגדרות בצד אפליקציית האינטרנט שפועלת בשרת זה. הגדרות האבטחה של יישום אינטרנט אינן יכולות אלא לקיים אינטראקציה עם הגדרות האבטחה של שרת האינטרנט, אם לא מסיבה אחרת מלבד זאת, יישום אינטרנט אינו יכול אלא לקיים אינטראקציה עם שרת האינטרנט. לא בכדי עברנו לטומקט, כי... ל-Tomcat יש ארכיטקטורה מתוארת היטב (ראה " ארכיטקטורת Apache Tomcat 8 "). מהתיאור של ארכיטקטורה זו ברור כי Tomcat, כשרת אינטרנט, מייצג את אפליקציית האינטרנט כהקשר מסוים, אשר נקרא " Tomcat Context ". הקשר זה מאפשר לכל יישום אינטרנט לקבל הגדרות משלו, מבודדות מיישומי אינטרנט אחרים. בנוסף, יישום האינטרנט יכול להשפיע על ההגדרות של הקשר זה. גמיש ונוח. להבנה מעמיקה יותר, אנו ממליצים לקרוא את המאמר " הבנת מיכלי ההקשר של Tomcat " ואת קטע התיעוד של Tomcat " The Context Container ". כפי שצוין לעיל, אפליקציית האינטרנט שלנו יכולה להשפיע על ההקשר Tomcat של האפליקציה שלנו באמצעות /META-INF/context.xml. ואחת ההגדרות החשובות ביותר שאנו יכולים להשפיע עליהן היא ממלכות האבטחה. ממלכת אבטחה היא מעין "אזור אבטחה". אזור שעבורו מוגדרות הגדרות אבטחה ספציפיות. בהתאם לכך, בעת שימוש בממלכת אבטחה, אנו מיישמים את הגדרות האבטחה שהוגדרו עבור ממלכה זו. ממלכות אבטחה מנוהלות על ידי קונטיינר, כלומר. שרת אינטרנט, לא יישום האינטרנט שלנו. אנחנו יכולים רק לומר לשרת איזה היקף אבטחה צריך להתרחב לאפליקציה שלנו. התיעוד של Tomcat בסעיף " רכיב הממלכה " מתאר תחום כאוסף של נתונים על משתמשים ותפקידיהם לביצוע אימות. Tomcat מספקת סט של יישומי תחום אבטחה שונים, אחד מהם הוא " ממלכת Jaas ". לאחר שהבנו מעט טרמינולוגיה, בואו נתאר את ההקשר של 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: " נספח ב': תצורות כניסה לדוגמה ". בנוסף, חשוב שהקובץ הזה יבוצע חיפוש ראשון במשאבים. לכן, יישום האינטרנט שלנו יכול לספק את הקובץ הזה בעצמו. מאפיינים 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 הוא לאחסן ולהחזיר שם (או מזהה) כלשהו שמייצג את ה- Principal. עכשיו, יש לנו תחום אבטחה, יש לנו כיתות מנהלים. נותר למלא את הקובץ מהתכונה " configFile", aka login configuration file. ניתן למצוא את התיאור שלו בתיעוד של Tomcat: " רכיב הממלכה ".
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 הוא אולי אחד הדברים המעניינים ביותר ב-JAAS. התיעוד הרשמי יעזור לנו בפיתוח LoginModule: " שירות Java Authentication and Authorization (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>
ציינו את השם של תחום האבטחה שלנו וציינו את שיטת האימות - BASIC. זהו אחד מסוגי האימות המתוארים בממשק ה-API של Servlet בסעיף " 13.6 אימות ". נשאר נ
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION