מדריך לשירות אימות והרשאות Java (JAAS)

ג'אווה טופ

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

1. סקירה כללית

שירות אימות ואישור Java (JAAS) הוא מסגרת אבטחה ברמה נמוכה של Java SE מגדיל את מודל האבטחה מאבטחה מבוססת קוד לאבטחה מבוססת משתמש. אנו יכולים להשתמש ב- JAAS לשתי מטרות:

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

במדריך זה נסקור כיצד להגדיר את JAAS ביישום לדוגמא על ידי יישום ותצורה של ממשקי ה- API השונים שלו, במיוחד LoginModule.

2. איך JAAS עובד

בעת שימוש ב- JAAS ביישום, מעורבים כמה ממשקי API:

  • CallbackHandler: משמש לאיסוף אישורי משתמש ומסופק אופציונלי בעת יצירת ה- LoginContext
  • תְצוּרָה: אחראי לטעינה LoginModule יישומים וניתן לספק אותם באופן אופציונלי ב LoginContext יצירה
  • LoginModule: משמש ביעילות לאימות משתמשים

נשתמש ביישום ברירת המחדל עבור ה- תְצוּרָה ממשק API ולספק יישומים משלנו עבור CallbackHandler וה LoginModule ממשקי API.

3. מתן CallbackHandler יישום

לפני שנחפור ב LoginModule היישום, אנחנו צריכים קודם לספק יישום עבור CallbackHandler ממשק, המשמש לאיסוף אישורי משתמש.

יש לה שיטה אחת, ידית(), שמקבל מערך של התקשר חזרהס. בנוסף, JAAS כבר מספקת רבים התקשר חזרה יישומים, ואנחנו נשתמש ב- NameCallback ו PasswordCallback לאיסוף שם המשתמש והסיסמה, בהתאמה.

בוא נראה את היישום שלנו של CallbackHandler מִמְשָׁק:

מחלקה ציבורית ConsoleCallbackHandler מיישמת CallbackHandler {@Override ידית חלל ציבורית (Callback [] callbacks) זורקת UnsupportedCallbackException {Console console = System.console (); עבור (Callback callback: callbacks) {if (callback instance of NameCallback) {NameCallback nameCallback = (NameCallback) callback; nameCallback.setName (console.readLine (nameCallback.getPrompt ())); } אחר אם (מופע החזרה של PasswordCallback) {PasswordCallback passwordCallback = (PasswordCallback) החזרה; passwordCallback.setPassword (console.readPassword (passwordCallback.getPrompt ())); } אחר {זורק חידוש לא-נתמך בקולבק (התקשרות חוזרת); }}}}

לכן, כדי להנחות ולקרוא את שם המשתמש, השתמשנו ב:

NameCallback nameCallback = (NameCallback) התקשרות חוזרת; nameCallback.setName (console.readLine (nameCallback.getPrompt ()));

באופן דומה, כדי לבקש ולקרוא את הסיסמה:

PasswordCallback passwordCallback = (PasswordCallback) התקשרות חוזרת; passwordCallback.setPassword (console.readPassword (passwordCallback.getPrompt ()));

בהמשך נראה כיצד להתקשר ל- CallbackHandler בעת יישום ה- LoginModule.

4. מתן LoginModule יישום

לשם פשטות, אנו נספק יישום המאחסן משתמשים בקוד קשיח. אז בואו נקרא לזה InMemoryLoginModule:

מחלקה ציבורית InMemoryLoginModule מיישם LoginModule {פרטית סופית סטרינג מחרוזת USERNAME = "testuser"; סופי סטטי פרטי מחרוזת PASSWORD = "testpassword"; נושא פרטי פרטי; CallbackHandler פרטי callbackHandler; מפה פרטית sharedState; אפשרויות מפה פרטיות; כניסה בוליאנית פרטיתSucceeded = false; משתמש עיקרי פרטי עיקרי; // ...}

בסעיפי המשנה הבאים אנו נותנים יישום לשיטות החשובות יותר: לְאַתחֵל(), התחברות(), ו לְבַצֵעַ().

4.1. לְאַתחֵל()

ה LoginModule נטען תחילה ואז מאותחל עם נושא ו CallbackHandler. בנוסף, LoginModules יכולים להשתמש ב- מַפָּה לשיתוף נתונים בינם לבין עצמם, ועוד מַפָּה לאחסון נתוני תצורה פרטיים:

האתחול של הריק הציבורי (נושא נושא, CallbackHandler callbackHandler, Map sharedState, אפשרויות מפה) {this.subject = נושא; this.callbackHandler = callbackHandler; this.sharedState = sharedState; this.options = אפשרויות; }

4.2. התחברות()

בתוך ה התחברות() שיטה, אנו קוראים את CallbackHandler.handle () שיטה עם NameCallback ו PasswordCallback כדי לדרוש ולקבל את שם המשתמש והסיסמה. לאחר מכן, אנו משווים את האישורים המסופקים הללו עם המקודדים הקשיחים:

@Override כניסה בוליאנית ציבורית () זורקת LoginException {NameCallback nameCallback = NameCallback חדש ("שם משתמש:"); PasswordCallback passwordCallback = PasswordCallback חדש ("סיסמה:", שקר); נסה את {callbackHandler.handle (Callback חדש [] {nameCallback, passwordCallback}); שם משתמש מחרוזת = nameCallback.getName (); סיסמת מחרוזת = מחרוזת חדשה (passwordCallback.getPassword ()); אם (USERNAME.equals (שם משתמש) && PASSWORD.equals (סיסמה)) {loginSucceeded = true; }} לתפוס (IOException | לא נתמך CallbackException e) {// ...} כניסה חזרה הצליח; }

ה התחברות() השיטה צריכה לחזור נָכוֹן למבצע מוצלח ו שֶׁקֶר עבור כניסה נכשלה.

4.3. לְבַצֵעַ()

אם כולם קוראים ל LoginModule # כניסה להצליח, אנחנו עדכן את נושא עם תוספת קֶרֶן:

@Override התחייבות בוליאנית ציבורית () זורק LoginException {if (! LoginSucceeded) {return false; } userPrincipal = UserPrincipal חדש (שם משתמש); subject.getPrincipals (). הוסף (userPrincipal); לחזור אמיתי; }

אחרת ה לְהַפִּיל() שיטה נקראת.

בשלב זה, שלנו LoginModule היישום מוכן ויש להגדירו כך שניתן יהיה לטעון אותו באופן דינמי באמצעות תְצוּרָה ספק שירות.

5. LoginModule תְצוּרָה

JAAS משתמש ב- תְצוּרָה ספק השירות לטעון LoginModules בזמן ריצה. כברירת מחדל, הוא מספק ומשתמש ב- ConfigFile יישום היכן LoginModules מוגדרים באמצעות קובץ כניסה. לדוגמה, הנה תוכן הקובץ המשמש עבורנו LoginModule:

jaasApplication {com.baeldung.jaas.loginmodule.InMemoryLoginModule נדרש איתור באגים = true; };

כמו שאנו יכולים לראות, סיפקנו את שם הכיתה המלא של ה- LoginModule יישום, א נדרש דגל, ואפשרות לניפוי באגים.

לבסוף, שים לב שאנחנו יכולים גם לציין את קובץ הכניסה דרך ה- java.security.auth.login.config מאפיין מערכת:

$ java -Djava.security.auth.login.config = src / main / resources / jaas / jaas.login.config

אנו יכולים גם לציין קובץ כניסה אחד או יותר דרך הנכס login.config.url בקובץ האבטחה של Java, $ {java.home} /jre/lib/security/java.security:

login.config.url.1 = קובץ: $ {user.home} /. java.login.config

6. אימות

קוֹדֶם כֹּל, יישום מאתחל את תהליך האימות על ידי יצירת a LoginContext למשל. לשם כך, אנו יכולים להסתכל על הבנאי המלא כדי לקבל מושג לגבי מה שאנחנו צריכים כפרמטרים:

LoginContext (שם מחרוזת, נושא נושא, CallbackHandler callbackHandler, תצורת תצורה)
  • שֵׁם: משמש כאינדקס לטעינת המקבילים בלבד LoginModuleס
  • נושא: מייצג משתמש או שירות שרוצים להתחבר
  • callbackHandler: אחראי על העברת אישורי המשתמש מהיישום אל LoginModule
  • config: אחראי לטעינה LoginModules התואמים לפרמטר השם

כאן נשתמש בבנאי העמוס בו אנו נספק את שלנו CallbackHandler יישום:

LoginContext (שם מחרוזת, CallbackHandler callbackHandler)

עכשיו שיש לנו CallbackHandler ותצורה מוגדרת LoginModule, אנו יכולים להתחיל את תהליך האימות על ידי אתחול א LoginContext לְהִתְנַגֵד:

LoginContext loginContext = LoginContext חדש ("jaasApplication", ConsoleCallbackHandler חדש ());

בנקודה זו, אנחנו יכולים להפעיל את התחברות() שיטה לאימות המשתמש:

loginContext.login ();

ה התחברות() השיטה, בתורו, יוצרת מופע חדש שלנו LoginModule וקוראת לזה התחברות() שיטה. וגם לאחר אימות מוצלח, אנו יכולים לאחזר את המאומת נושא:

נושא הנושא = loginContext.getSubject ();

עכשיו, בוא נפעיל יישום לדוגמא שיש לו את LoginModule חיווט:

חבילה נקייה $ mvn $ java -Djava.security.auth.login.config = src / main / resources / jaas / jaas.login.config \ -classpath target / core-java-security-2-0.1.0-SNAPSHOT.jar com.baeldung.jaas.Jaas אימות

כאשר נתבקש לספק את שם המשתמש והסיסמה, נשתמש בודק ו סיסמת מבחן כתעודות.

7. אישור

הרשאה נכנסת לפעולה כאשר המשתמש מחובר לראשונה ומשויך ל- AccessControlContext. באמצעות מדיניות האבטחה של Java, אנו יכולים להעניק זכויות בקרת גישה אחת או יותר קֶרֶןס. לאחר מכן נוכל למנוע גישה לקוד רגיש על ידי התקשרות ל- SecurityManager # check הרשאה שיטה:

SecurityManager.checkPermission (היתר הרשאה)

7.1. הגדרת הרשאות

זכות בקרת כניסה או הרשאה היא היכולת לבצע פעולה על משאב. אנו יכולים ליישם הרשאה על ידי סיווג משנה של ה- רְשׁוּת מעמד מופשט. לשם כך, עלינו לספק שם משאב ומערכת פעולות אפשריות. לדוגמא, אנו יכולים להשתמש FilePermission כדי להגדיר זכויות בקרת גישה בקבצים. פעולות אפשריות הן לקרוא, לִכתוֹב, לבצע, וכולי. עבור תרחישים שבהם אין צורך בפעולות, אנו עשויים פשוט להשתמש ב- BasicPermision.

לאחר מכן, נספק יישום הרשאה דרך ה- ResourcePermission מחלקה שבה למשתמשים עשויה להיות הרשאה לגשת למשאב:

מחלקה סופית ציבורית ResourcePermission מרחיב את BasicPermission {public ResourcePermission (שם מחרוזת) {super (name); }}

בהמשך, נגדיר ערך עבור הרשאה זו באמצעות מדיניות האבטחה של Java.

7.2. הענקת אישורים

בדרך כלל, אנחנו לא צריכים לדעת את תחביר קובץ המדיניות מכיוון שאנחנו תמיד יכולים להשתמש בכלי המדיניות כדי ליצור אחד. בואו נסתכל על קובץ המדיניות שלנו:

הענק com.sun.security.auth.UserPrincipal testuser {הרשאה com.baeldung.jaas.ResourcePermission "test_resource"};

במדגם זה, הענקנו את test_resource אישור ל בודק מִשׁתַמֵשׁ.

7.3. בודק הרשאות

פעם ה נושא מאומת ומוגדרות הרשאות, נוכל לבדוק גישה על ידי התקשרות ל- נושא מס 'doAs אוֹ נושא # doAsPrivilieged שיטות סטטיות. לצורך כך אנו נספק א PrivilegedAction שם אנו יכולים להגן על הגישה לקוד רגיש. בתוך ה לָרוּץ() שיטה, אנו מכנים SecurityManager # check הרשאה שיטה כדי להבטיח שלמשתמש המאומת יש את test_resource רְשׁוּת:

מחלקה ציבורית ResourceAction מיישמת את PrivilegedAction {@Override Object public run () {SecurityManager sm = System.getSecurityManager (); אם (sm! = null) {sm.checkPermission (ResourcePermission חדש ("test_resource")); } System.out.println ("יש לי גישה ל- test_resource!"); החזר אפס; }}

הדבר האחרון הוא להתקשר ל נושא מס 'doAsPrivileged שיטה:

נושא הנושא = loginContext.getSubject (); PrivilegedAction privilegedAction = ResourceAction חדש (); נושא.doAsPrivileged (נושא, privilegedAction, null);

כמו האימות, נפעיל יישום פשוט לאישור שבו, בנוסף ל LoginModule, אנו מספקים קובץ תצורת הרשאות:

חבילה נקייה $ mvn $ java -Djava.security.manager -Djava.security.policy = src / main / resources / jaas / jaas.policy \ -Djava.security.auth.login.config = src / main / resources / jaas / jaas.login.config \ -classpath target / core-java-security-2-0.1.0-SNAPSHOT.jar com.baeldung.jaas.JaasAuthorization

8. מסקנה

במאמר זה הראינו כיצד ליישם את JAAS על ידי בחינת הכיתות והממשקים העיקריים והצגת כיצד להגדיר אותם. במיוחד, יישמנו ספק שירות LoginModule.

כרגיל, הקוד במאמר זה זמין באתר GitHub.

תחתית Java

רק הכרזתי על החדש למד אביב קורס, המתמקד ביסודות האביב 5 ומגף האביב 2:

>> בדוק את הקורס

$config[zx-auto] not found$config[zx-overlay] not found