שלוט במושב עם אבטחת אביב
1. סקירה כללית
במאמר זה נמחיש כיצד Spring Security מאפשר לנו לשלוט על הפעלות ה- HTTP שלנו.
בקרה זו נעה בין פסק זמן להפעלה להפעלת הפעלות במקביל ותצורות אבטחה מתקדמות אחרות.
2. מתי נוצר מושב?
אנו יכולים לשלוט במדויק מתי ההפעלה שלנו תיווצר וכיצד אבטחת האביב תקשר איתה:
- תמיד- מושב ייווצר תמיד אם אחד עדיין לא קיים
- אם נדרש- מושב ייווצר רק במידת הצורך (בְּרִירַת מֶחדָל)
- לעולם לאהמסגרת לעולם לא תיצור מושב עצמו, אך היא תשתמש בו אם היא כבר קיימת
- חסר מדינה- שום הפעלה לא תיווצר או תשמש את Spring Security
...
תצורת Java:
תצורת הריק המוגנת על ידי @Override (HttpSecurity http) זורקת חריג {http.sessionManagement () .sessionCreationPolicy (SessionCreationPolicy.IF_REQUIRED)}
חשוב מאוד להבין זאת תצורה זו שולטת רק במה ש- Spring Security עושה - לא כל היישום. Spring Security אולי לא תיצור את ההפעלה אם נורה לה שלא, אבל האפליקציה שלנו עשויה!
כברירת מחדל, אביב אבטחה תיצור הפעלה כשיזדקק לה - זה "אם נדרש“.
ל יישום חסר מדינה יותר, ה "לעולם לא"האפשרות תבטיח שאבטחת אביב עצמה לא תיצור הפעלה כלשהי; עם זאת, אם היישום יוצר כזה, Spring Security תשתמש בו.
לבסוף, האפשרות המחמירה ביותר ליצירת הפעלות - “חסר מדינה" - הוא להבטיח שהיישום כלל לא ייצור הפעלה כלשהי.
זה הוצג באביב 3.1 ויעיל לדלג על חלקים בשרשרת המסננים של Spring Security - בעיקר החלקים הקשורים להפעלה, כגון HttpSessionSecurityContextRepository, SessionManagementFilter, RequestCacheFilter.
למנגנוני בקרה קפדניים יותר יש המשמעות הישירה לכך אין להשתמש בעוגיות וכך צריך לאמת מחדש כל בקשה ובקשה. ארכיטקטורה חסרת אזרחות זו משחקת היטב עם ממשקי ה- API של REST ומגבלת חוסר האמונות שלהם. הם גם עובדים היטב עם מנגנוני אימות כגון אימות בסיסי ועיכול.
3. מתחת למכסה המנוע
לפני ביצוע תהליך האימות, Spring Security תפעיל מסנן האחראי על שמירת הקשר האבטחה בין בקשות - SecurityContextPersistenceFilter. ההקשר יישמר על פי אסטרטגיה - HttpSessionSecurityContextRepository כברירת מחדל - המשתמשת באתר HTTP כאחסון.
למקפידים create-session = "חסר מדינה" תכונה, אסטרטגיה זו תוחלף באחרת - NullSecurityContextRepository - ו שום הפעלה לא תיווצר או תשמש כדי לשמור על ההקשר.
4. בקרת מושבים במקביל
כאשר משתמש שכבר מאומת מנסה לאמת שוב, היישום יכול להתמודד עם אירוע זה באחת מכמה דרכים. זה יכול לפסול את ההפעלה הפעילה של המשתמש ולאמת את המשתמש שוב באמצעות הפעלה חדשה, או לאפשר לשני ההפעלות להתקיים במקביל.
הצעד הראשון בהפעלת המקביל בקרת הפעלה התמיכה היא להוסיף את המאזין הבא ב- web.xml:
org.springframework.security.web.session.HttpSessionEventPublisher
או הגדר אותו כשעועית - כדלקמן:
@Bean הציבור HttpSessionEventPublisher httpSessionEventPublisher () {החזר HttpSessionEventPublisher חדש (); }
זה חיוני כדי לוודא שמדובר ברישום הפעלות של Spring Security הודיעו כאשר מושב נהרס.
כדי לאפשר את התרחיש המאפשר הפעלות מרובות במקביל לאותו משתמש יש להשתמש באלמנט בתצורת XML:
לחלופין, באמצעות תצורת Java:
תצורת הריק המוגנת על ידי @Override (HttpSecurity http) זורקת חריג {http.sessionManagement (). MaximumSessions (2)}
5. פסק זמן של מושב
5.1. טיפול בפסק זמן של מושב
לאחר שתם הזמן הקצוב לפגישה, אם המשתמש שולח בקשה עם מזהה מושב שפג תוקפו, הם יופנו לכתובת אתר הניתנת להגדרה דרך מרחב השמות:
באופן דומה, אם המשתמש שולח בקשה עם מזהה הפעלה שאינו פג, אלא לחלוטין לא חוקי, הם יופנו גם לכתובת אתר הניתנת להגדרה:
...
תצורת Java המתאימה:
http.sessionManagement () .expiredUrl ("/ sessionExpired.html") .invalidSessionUrl ("/ invalidSession.html");
5.2. הגדר את פסק זמן ההפעלה עם Spring Boot
אנו יכולים להגדיר בקלות את ערך הזמן הקצוב להפעלה של השרת המוטמע באמצעות מאפיינים:
server.servlet.session.timeout = 15 מטר
אם לא נציין את יחידת משך הזמן, אביב ייניח שזה שניות.
בקצרה, עם תצורה זו, לאחר 15 דקות של חוסר פעילות, תוקף ההפעלה יפוג. הפגישה לאחר פרק זמן זה נחשבת כלא חוקית.
אם הגדרנו את הפרויקט שלנו לשימוש ב- Tomcat, עלינו לזכור שהוא תומך רק בדיוק דקה לפסק זמן של הפעלה, עם מינימום דקה. פירוש הדבר שאם נציין ערך פסק זמן של שנות ה -170 לדוגמא, זה יביא לפסק זמן של 2 דקות.
לסיום, חשוב להזכיר שלמרות שמושב האביב תומך במאפיין דומה למטרה זו (spring.session.timeout), אם זה לא צוין, התצורה האוטומטית תחזור לערך המאפיין שהזכרנו לראשונה.
6. למנוע שימוש בפרמטרים של כתובות אתרים למעקב אחר פעילויות באתר
חשיפת מידע על הפעלות בכתובת האתר מהווה סיכון אבטחה הולך וגדל (ממקום 7 בשנת 2007 למקום 2 בשנת 2013 ברשימת 10 המובילים של OWASP).
החל מאביב 3.0, הלוגיקה של כתיבת כתובות אתרים שתוסיף את jsessionid לכתובת האתר ניתן כעת להשבית על ידי הגדרת ה- disable-url-rewriting = "true" בתוך ה מרחב שמות.
לחלופין, החל מ- Servlet 3.0, ניתן להגדיר את מנגנון המעקב אחר פעילויות באתר web.xml:
עוגייה
ותכניתית:
servletContext.setSessionTrackingModes (EnumSet.of (SessionTrackingMode.COOKIE));
זה בוחר היכן לאחסן את JSESSIONID - בקובץ ה- cookie או בפרמטר של URL.
7. הגנה על קיבוע מושב עם אבטחת אביב
המסגרת מציעה הגנה מפני התקפות טיפוסיות של פעילויות הפעלה על ידי הגדרת מה שקורה להפעלה קיימת כאשר המשתמש מנסה לאמת שוב:
...
תצורת Java המתאימה:
http.sessionManagement () .sessionFixation (). migrateSession ()
כברירת מחדל, Spring Security מאפשר הגנה זו ("migrateSession“) - באימות נוצר מושב HTTP חדש, הישן מבוטל והמאפיינים מהמושב הישן מועתקים.
אם זו לא ההתנהגות הרצויה, שתי אפשרויות אחרות זמינות:
- מתי "אף אחד"מוגדר, ההפעלה המקורית לא תבטל
- מתי "newSession"מוגדר, ייווצר הפעלה נקייה מבלי שתועתק אף אחת מהתכונות מההפעלה הישנה
8. עוגיית מושב מאובטחת
לאחר מכן נדון כיצד לאבטח את קובץ ה- cookie שלנו.
אנחנו יכולים להשתמש ב- http בלבד ו לבטח דגלים כדי לאבטח את קובץ ה- cookie שלנו:
- http רק: אם נכון, סקריפט הדפדפן לא יוכל לגשת לעוגיה
- לבטח: אם נכון, העוגיה תישלח רק דרך חיבור HTTPS
אנו יכולים לקבוע את הדגלים האלה עבור קובץ ה- cookie שלנו web.xml:
נכון אמיתי
אפשרות תצורה זו זמינה מאז Servlet 3. Java כברירת מחדל, http בלבד הוא נכון ו לבטח הוא שקר.
בואו נסתכל גם על תצורת Java המתאימה:
מחלקה ציבורית MainWebAppInitializer מיישם את WebApplicationInitializer {@Override public void onStartup (ServletContext sc) זורק ServletException {// ... sc.getSessionCookieConfig (). setHttpOnly (true); sc.getSessionCookieConfig (). setSecure (נכון); }}
אם אנו משתמשים באביב אתחול, אנו יכולים להגדיר את הדגלים הללו שלנו application.properties:
server.servlet.session.cookie.http-only = true server.servlet.session.cookie.secure = true
לבסוף, אנו יכולים להשיג זאת גם באופן ידני באמצעות a לְסַנֵן:
SessionFilter מחלקה ציבורית מיישמת את המסנן {@Override public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) זורק IOException, ServletException {HttpServletRequest req = (HttpServletRequest) בקשה; HttpServletResponse res = (HttpServletResponse) תגובה; קובץ Cookie [] allCookies = req.getCookies (); אם (allCookies! = null) {הפעלת Cookie = Arrays.stream (allCookies) .filter (x -> x.getName (). שווה ("JSESSIONID")) .findFirst (). orElse (null); אם (session! = null) {session.setHttpOnly (true); session.setSecure (נכון); res.addCookie (הפעלה); }} chain.doFilter (req, res); }}
9. עבודה עם המושב
9.1. שעועית Scoped שעועית
ניתן להגדיר שעועית עם מוֹשָׁב היקף פשוט באמצעות ההערה @Scope על שעועית המוצהרת בהקשר האינטרנט:
@Component @Scope ("מושב") בכיתה ציבורית Foo {..}
או עם XML:
לאחר מכן, פשוט ניתן להזריק את השעועית לשעועית אחרת:
@ Foo theFoo פרטית אוטומטית;
ואביב יקשור את השעועית החדשה למחזור החיים של מושב ה- HTTP.
9.2. הזרקת המושב הגולמי לבקר
ניתן להזריק את מושב ה- HTTP הגולמי ישירות ל- בקר שיטה:
@RequestMapping (..) חלל ציבורי fooMethod (הפעלת HttpSession) {session.setAttribute (Constants.FOO, Foo חדש ()); // ... Foo foo = (Foo) session.getAttribute (Constants.FOO); }
9.3. השגת הפגישה הגולמית
ניתן להשיג את מושב ה- HTTP הנוכחי באמצעות תוכנה ממשק API גולמי של Servlet:
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes (); הפעלת HttpSession = attr.getRequest (). GetSession (נכון); // נכון == אפשר ליצור
10. מסקנה
במאמר זה דנו בניהול מושבים עם Spring Security. כמו כן, עיון האביב מכיל שאלות נפוצות טובות מאוד בנושא ניהול מושבים.
כמו תמיד, הקוד המוצג במאמר זה זמין באתר Github. זהו פרויקט מבוסס Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.