ממשק API לאבטחה של ג'קרטה EE 8

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

ממשק ה- API לאבטחה של ג'קרטה EE 8 הוא הסטנדרט החדש ודרך ניידת לטיפול בבעיות אבטחה במכולות Java.

במאמר זה, נבחן את שלוש התכונות המרכזיות של ה- API:

  1. מנגנון אימות HTTP
  2. חנות זהויות
  3. הקשר ביטחוני

ראשית נבין כיצד להגדיר את היישומים שסופקו ואז כיצד ליישם יישום מותאם אישית.

2. תלות Maven

כדי להגדיר את ה- API של אבטחת ג'קרטה EE 8, אנו זקוקים ליישום המסופק על ידי השרת או ליישום מפורש.

2.1. שימוש ביישום השרת

שרתים תואמי ג'קרטה EE 8 כבר מספקים יישום עבור ה- API של אבטחת ג'קרטה EE 8, ולכן אנו זקוקים רק לחפץ Maven של פרופיל האינטרנט של ג'קרטה EE:

  javax javaee-web-api 8.0 מסופק 

2.2. שימוש ביישום מפורש

ראשית, אנו מציינים את חפץ Maven עבור ממשק ה- API לאבטחה של ג'קרטה EE 8:

  javax.security.enterprise javax.security.enterprise-api 1.0 

ואז נוסיף יישום, למשל, Soteria - יישום הייחוס:

  org.glassfish.soteria javax.security.enterprise 1.0 

3. מנגנון אימות HTTP

לפני ג'קרטה EE 8, הגדרנו מנגנוני אימות באופן הצהרתי באמצעות ה- web.xml קוֹבֶץ.

בגרסה זו, ה- API של אבטחת ג'קרטה EE 8 תכנן את החדש Http אימות מכניזם ממשק כתחליף. לכן, יישומי אינטרנט יכולים כעת להגדיר מנגנוני אימות על ידי מתן יישומים של ממשק זה.

למרבה המזל, המכולה כבר מספקת יישום לכל אחת משלוש שיטות האימות המוגדרות במפרט Servlet: אימות HTTP בסיסי, אימות מבוסס טופס ואימות מותאם אישית מבוסס טופס.

הוא גם מספק הערה להפעלת כל יישום:

  1. @BasicAuthenticationMechanismDefinition
  2. @FormAuthenticationMechanismDefinition
  3. @CustomFormAuthenrticationMechanismDefinition

3.1. אימות HTTP בסיסי

כאמור לעיל, יישום אינטרנט יכול להגדיר את אימות ה- HTTP הבסיסי רק באמצעות @BasicAuthenticationMechanism הערת הגדרה על שעועית CDI:

@BasicAuthenticationMechanismDefinition (realmName = "userRealm") @ApplicationScoped מחלקה ציבורית AppConfig {}

בשלב זה, מיכל Servlet מחפש ומיישם את היישום המסופק של Http אימות מכניזם מִמְשָׁק.

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

WWW-Authenticate: Basic realm = "userRealm"

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

// user = baeldung, password = baeldung הרשאה: בסיסי YmFlbGR1bmc6YmFlbGR1bmc = 

שים לב כי תיבת הדו-שיח המוצגת לצורך מתן אישורים מגיעה מהדפדפן ולא מהשרת.

3.2. אימות HTTP מבוסס טופס

ה @FormAuthenticationMechanismDefinition ביאור מפעיל אימות מבוסס טופס כהגדרתם במפרט Servlet.

אז יש לנו אפשרות לציין את דפי הכניסה והשגיאה או להשתמש בדפי ברירת המחדל הסבירים /התחברות ו /שגיאת התחברות:

@FormAuthenticationMechanismDefinition (loginToContinue = @LoginToContinue (loginPage = "/login.html", errorPage = "/ login-error.html")) @ApplicationScoped מחלקה ציבורית AppConfig {}

כתוצאה מהפעלת loginPage, על השרת לשלוח את הטופס ללקוח:

לאחר מכן הלקוח צריך לשלוח את הטופס לתהליך אימות גיבוי שהוגדר מראש המסופק על ידי המכולה.

3.3. אימות HTTP מבוסס טופס מותאם אישית

יישום אינטרנט יכול להפעיל יישום אימות מבוסס טופס מותאם אישית באמצעות ההערה @CustomFormAuthenticationMechanism הגדרה:

@CustomFormAuthenticationMechanismDefinition (loginToContinue = @LoginToContinue (loginPage = "/login.xhtml")) @ApplicationScoped מחלקה ציבורית AppConfig {}

אך שלא כמו אימות מבוסס טופס המוגדר כברירת מחדל, אנו מגדירים דף כניסה מותאם אישית ומפעילים את ה- SecurityContext.authenticate () שיטה כתהליך אימות גיבוי.

בואו נסתכל על הגיבוי LoginBean כמו כן, המכיל את לוגיקת הכניסה:

@ Name @ RequestScoped מחלקה ציבורית LoginBean {@ הזן SecurityContext פרטי אבטחהקונטקסט; שם משתמש מחרוזת פרטי @NotNull; סיסמת מחרוזת פרטית @NotNull; כניסה בטלנית ציבורית () {אישורי כניסה = שם משתמש חדש סיסמה כניסה (שם משתמש, סיסמה חדשה (סיסמה)); AuthenticationStatus status = securityContext .authenticate (getHttpRequestFromFacesContext (), getHttpResponseFromFacesContext (), withParams (). Credential (credential)); // ...} // ...}

כתוצאה מהפעלת המנהג login.xhtml דף, הלקוח מגיש את הטופס שהתקבל אל כניסה שעועיתס התחברות() שיטה:

//... 

3.4. מנגנון אימות מותאם אישית

ה Http אימות מכניזם ממשק מגדיר שלוש שיטות. החשוב ביותר הוא validateRequest () שעלינו לספק יישום.

התנהגות ברירת המחדל לשתי השיטות האחרות, secureResponse () ו cleanSubject (), מספיק ברוב המקרים.

בואו נסתכל על יישום לדוגמא:

@ApplicationScoped המחלקה הציבורית CustomAuthentication מיישמת את HttpAuthenticationMechanism {@Override Public AuthenticationStatus validateRequest (HttpServletRequest בקשה, HttpServletResponse תגובה, HttpMessageContext httpMsgContext) זורק AuthenticationException {String = שם בקשה. " סיסמת מחרוזת = response.getParameter ("סיסמה"); // ללעוג ל- UserDetail, אך בחיים האמיתיים אנו יכולים להשיג אותו ממסד נתונים UserDetail userDetail = findByUserNameAndPassword (שם משתמש, סיסמה); אם (userDetail! = null) {return httpMsgContext.notifyContainerAboutLogin (CustomPrincipal חדש (userDetail), HashSet חדש (userDetail.getRoles ())); } להחזיר httpMsgContext.responseUnauthorized (); } // ...}

כאן, היישום מספק את ההיגיון העסקי של תהליך האימות, אך בפועל, מומלץ להאציל את ה- IdentityStore דרך ה IdentityStoreHandler בy הפעלת לְאַמֵת.

הערנו גם על היישום עם @ApplicationScoped ביאור כיוון שאנחנו צריכים להפוך אותו לתומך ב- CDI.

לאחר אימות תקף של האישור, ואחזור של תפקידי משתמש בסופו של דבר, היישום אמור להודיע ​​למכולה אז:

HttpMessageContext.notifyContainerAboutLogin (מנהל ראשי, קבוצות קבוצות)

3.5. אכיפת אבטחת סרוולט

יישום אינטרנט יכול לאכוף מגבלות אבטחה באמצעות ה- @ServletSecurity ביאור על יישום Servlet:

@WebServlet ("/ מאובטח") @ServletSecurity (value = @HttpConstraint (rollerAllowed = {"admin_role"}), httpMethodConstraints = {@HttpMethodConstraint (value = "GET", roleAllowed = {"user_role"}), @HttpMethodCon = "POST" ,rollerAllowed = {"admin_role"}}}) מחלקה ציבורית SecuredServlet מרחיב את HttpServlet {}

להערה זו שתי תכונות - httpMethodConstraints ו ערך; httpMethodConstraints משמש כדי לציין מגבלה אחת או יותר, שכל אחת מהן מייצגת בקרת גישה לשיטת HTTP על ידי רשימת תפקידים מותרים.

לאחר מכן המכולה תבדוק, לכל דבר דפוס url ושיטת HTTP, אם למשתמש המחובר יש את התפקיד המתאים לגישה למשאב.

4. חנות זהויות

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

IdentityStore מיועד ומעודד לשמש את Http אימות מנגנון דרך נקרא IdentityStoreHandler מִמְשָׁק. יישום ברירת המחדל של ה- IdentityStoreHandler מסופק על ידי סרוולטמְכוֹלָה.

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

4.1. חנויות זהות מובנות

על השרת התואם של ג'קרטה EE לספק יישומים עבור שתי חנויות הזהות: מסד נתונים ו- LDAP.

בסיס הנתונים IdentityStore היישום מאתחל על ידי העברת נתוני תצורה ל- @ DataBaseIdentityStoreDefinition ביאור:

@ DatabaseIdentityStoreDefinition (dataSourceLookup = "java: comp / env / jdbc / securityDS", callerQuery = "בחר סיסמה ממשתמשים שם שם משתמש =?", GroupQuery = "בחר GROUPNAME מקבוצות שבהן שם המשתמש =?", עדיפות = 30) @ ApplicationScoped ציבור מחלקה AppConfig {}

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

IdentityStore עם עדיפות גבוהה מעובד מאוחר יותר על ידי IdentityStoreHandler.

כמו מסד הנתונים, יישום LDAP IdentityStore מאותחל באמצעות ה- @LdapIdentityStoreDefinition על ידי העברת נתוני תצורה:

@LdapIdentityStoreDefinition (url = "ldap: // localhost: 10389", callerBaseDn = "ou = מתקשר, dc = baeldung, dc = com", groupSearchBase = "ou = group, dc = baeldung, dc = com", groupSearchFilter = " (& (חבר =% s) (objectClass = groupOfNames)) ") @ApplicationScoped מחלקה ציבורית AppConfig {}

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

4.2. יישום מותאם אישית IdentityStore

ה IdentityStore ממשק מגדיר ארבע שיטות ברירת מחדל:

ברירת מחדל CredentialValidationResult אימות (אישורי אישורים) ברירת מחדל הגדר getCallerGroups (CredentialValidationResult validationResult) ברירת מחדל int עדיפות () ברירת מחדל הגדר validationTypes ()

ה עדיפות() השיטה מחזירה ערך לסדר האיטרציה שעובד על ידי יישום זה IdentityStoreHandler. An IdentityStore עם עדיפות נמוכה יותר מטופל תחילה.

כברירת מחדל, an IdentityStore מעבד את אימות האישורים (ValidationType.VALIDATE) ואחזור קבוצתי (ValidationType.PROVIDE_GROUPS). אנו יכולים לעקוף התנהגות זו כך שתוכל לספק יכולת אחת בלבד.

לפיכך, אנו יכולים להגדיר את IdentityStore לשמש רק לאימות אישורים:

@ Override public הגדר validationTypes () {החזר EnumSet.of (ValidationType.VALIDATE); }

במקרה זה, עלינו לספק יישום עבור ה- לְאַמֵת() שיטה:

@ApplicationScoped מחלקה ציבורית InMemoryIdentityStore מיישם את IdentityStore {// init מקובץ או ממשתמשי מפה פרטיים מקודדים = HashMap חדש (); @ Override public int עדיפות () {return 70; } @Override public הגדר validationTypes () {return EnumSet.of (ValidationType.VALIDATE); } אימות ציבורי של CredentialValidationResult (UsernamePasswordCredential) {UserDetails user = users.get (credential.getCaller ()); אם (credential.compareTo (user.getLogin (), user.getPassword ())) {להחזיר CredentialValidationResult חדש (user.getLogin ()); } להחזיר את INVALID_RESULT; }}

או שאנחנו יכולים לבחור להגדיר את IdentityStore כך שניתן להשתמש בו רק לאחזור קבוצתי:

@Override ציבורי הגדר validationTypes () {החזר EnumSet.of (ValidationType.PROVIDE_GROUPS); }

עלינו לספק יישום עבור ה- getCallerGroups () שיטות:

@ApplicationScoped מחלקה ציבורית InMemoryIdentityStore מיישם את IdentityStore {// init מקובץ או ממשתמשי מפה פרטיים מקודדים = HashMap חדש (); @ Override עדיפות ציבורית ציבורית () {חזרה 90; } @Override public הגדר validationTypes () {return EnumSet.of (ValidationType.PROVIDE_GROUPS); } @Override ציבורי הגדר getCallerGroups (CredentialValidationResult validationResult) {UserDetails user = users.get (validationResult.getCallerPrincipal (). GetName ()); להחזיר HashSet חדש (user.getRoles ()); }}

כי IdentityStoreHandler מצפה שהיישום יהיה שעועית CDI, אנחנו מקשטים אותה עם ApplicationScoped ביאור.

5. ממשק API להקשר אבטחה

ממשק ה- API לאבטחה של ג'קרטה EE 8 מספק נקודת גישה לאבטחה תכנותית דרך אבטחה הקשר מִמְשָׁק. זו חלופה כאשר מודל האבטחה ההצהרתי שנאכף על ידי המכולה אינו מספיק.

יישום ברירת המחדל של ה- אבטחה הקשר יש לספק ממשק בזמן ריצה כשעועית CDI, ולכן עלינו להזרים אותה:

@Inject SecurityContext securityContext;

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

5.1. אחזור נתוני שיחות

בגרסאות קודמות של ג'קרטה EE, היינו מאחזרים את קֶרֶן או לבדוק את החברות בתפקיד באופן שונה בכל מכולה.

בזמן שאנחנו משתמשים ב- getUserPrincipal () ו isUserInRole () שיטות של HttpServletRequest במיכל סרבל, שיטות דומות getCallerPrincipal () ו שיטות isCallerInRole () של ה EJBContext משמשים במיכל EJB.

ממשק ה- API החדש של ג'קרטה EE 8 לאבטחה סטנדרטי על ידי מתן שיטה דומה באמצעות אבטחה הקשר מִמְשָׁק:

ראשי getCallerPrincipal (); isCallerInRole בוליאני (תפקיד מחרוזת); הגדר getPrincipalsByType (סוג מחלקה);

ה getCallerPrincipal () השיטה מחזירה ייצוג ספציפי למכולה של המתקשר המאומת בזמן ש- getPrincipalsByType () השיטה מאחזרת את כל העקרונות מסוג מסוים.

זה יכול להיות שימושי במקרה שהמתקשר הספציפי ליישום שונה מזה של מיכל.

5.2. בודק גישה למשאבי אינטרנט

ראשית, עלינו להגדיר משאב מוגן:

@WebServlet ("/ protectedServlet") @ServletSecurity (@HttpConstraint (roleAllowed = "USER_ROLE")) מחלקה ציבורית ProtectedServlet מרחיב את HttpServlet {// ...}

ואז, כדי לבדוק את הגישה למשאב מוגן זה עלינו להפעיל את hasAccessToWebResource () שיטה:

securityContext.hasAccessToWebResource ("/ protectedServlet", "GET");

במקרה זה, השיטה מחזירה אמת אם המשתמש נמצא בתפקיד תפקיד משתמש.

5.3. אימות המתקשר באופן תכנותי

יישום יכול להפעיל באופן תכנותי את תהליך האימות על ידי הפעלת לְאַמֵת():

AuthenticationStatus authenticate (בקשת HttpServletRequest, HttpServletResponse, AuthenticationParameters פרמטרים);

לאחר מכן הודעה על המכולה והיא תפעיל, בתורו, את מנגנון האימות שהוגדר ליישום. AuthenticationParameters פרמטר מספק אישורים ל- Http אימות מכניזם:

withParams (). אישורים (אישורים)

ה הַצלָחָה ו SEND_FAILURE הערכים של AuthenticationStatus לעצב אימות מוצלח וכושל תוך כדי SEND_CONTINUE מאותת על סטטוס בתהליך האימות.

6. הפעלת הדוגמאות

לצורך הדגשת דוגמאות אלה, השתמשנו במבנה הפיתוח האחרון של שרת Open Liberty התומך בג'קרטה EE 8. זה מוריד ומותקן הודות לתוסף liberty-maven שיכול גם לפרוס את היישום ולהפעיל את השרת.

להפעלת הדוגמאות, פשוט גש למודול המתאים והפעל פקודה זו:

חירות חבילה נקייה mvn: לרוץ

כתוצאה מכך, Maven יוריד את השרת, יבנה, יפרוס ויפעיל את היישום.

7. מסקנה

במאמר זה סקרנו את התצורה וההטמעה של התכונות העיקריות של ה- API החדש של ג'קרטה EE 8 לאבטחה.

ראשית התחלנו להציג כיצד להגדיר את מנגנוני האימות המובנים כברירת מחדל וכיצד ליישם מכשיר מותאם אישית. מאוחר יותר ראינו כיצד להגדיר את חנות הזהות המובנית וכיצד ליישם חנות מותאמת אישית. ולבסוף, ראינו איך קוראים לשיטות של אבטחה הקשר.

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


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