Spring Security 5 ליישומים ריאקטיביים

1. הקדמה

במאמר זה נחקור תכונות חדשות של מסגרת Spring Security 5 לאבטחת יישומים ריאקטיביים. מהדורה זו מתואמת עם אביב 5 ומגף אביב 2.

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

2. הגדרת Maven

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

ההתקנה הבסיסית דורשת הצהרת הורים, סטרטר אינטרנט ותלות במתחילי אבטחה. נצטרך גם את מסגרת הבדיקה של Spring Security:

 org.springframework.boot spring-boot-starter-parent 2.2.6.RELEASE org.springframework.boot spring-boot-starter-webflux org.springframework.boot spring-boot-starter-security org.springframework.security spring-security- מבחן מבחן 

אנו יכולים לבדוק את הגרסה הנוכחית של מתג האבטחה של Spring Boot במייבן סנטרל.

3. הגדרת פרויקט

3.1. אתחול האפליקציה תגובתי

לא נשתמש בתקן @ SpringBootApplication תצורה אלא במקום זאת, הגדר שרת אינטרנט מבוסס Netty. Netty היא מסגרת מבוססת NIO אסינכרונית המהווה בסיס טוב ליישומים ריאקטיביים.

ה @EnableWebFlux ביאור מאפשר תצורה רגילה של Spring Web Reactive ליישום:

@ComponentScan (basePackages = {"com.baeldung.security"}) @EnableWebFlux class class SpringSecurity5Application {public static void main (String [] args) {try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext (SpringSecurity) NettyContext.class) .onClose (). Block (); }}

כאן, אנו יוצרים הקשר יישומי חדש ומחכים ש- Netty תיסגר על ידי התקשרות .onClose (). חסום () שרשרת בהקשר של Netty.

לאחר סגירת Netty, ההקשר ייסגר אוטומטית באמצעות נסה עם משאבים לַחסוֹם.

נצטרך ליצור שרת HTTP מבוסס Netty, מטפל לבקשות ה- HTTP והמתאם בין השרת למטפל:

@Bean NettyContext ציבורי nettyContext (הקשר ApplicationContext) {HttpHandler handler = WebHttpHandlerBuilder .applicationContext (context) .build (); מתאם ReactorHttpHandlerAdapter = חדש ReactorHttpHandlerAdapter (מטפל); HttpServer httpServer = HttpServer.create ("localhost", 8080); החזר httpServer.newHandler (מתאם) .block (); }

3.2. אביב תצורת אבטחה בכיתה

לתצורת האבטחה הבסיסית של אביב, ניצור מחלקת תצורה - אבטחהקונפיג.

כדי לאפשר תמיכה ב- WebFlux ב- Spring Security 5, עלינו רק לציין את ה- @EnableWebFluxSecurity ביאור:

@EnableWebFluxSecurity מחלקה ציבורית SecurityConfig {// ...}

עכשיו אנחנו יכולים לנצל את השיעור ServerHttpSecurity לבניית תצורת האבטחה שלנו.

שיעור זה הוא תכונה חדשה של אביב 5. זה דומה ל HttpSecurity בונה, אך הוא מופעל רק עבור יישומי WebFlux.

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

@Bean SecurityWebFilterChain הציבור securitygWebFilterChain (ServerHttpSecurity http) {להחזיר http.authorizeExchange () .anyExchange (). מאומת () .and (). Build (); }

כמו כן, נצטרך שירות פרטי משתמש. Spring Security מספקת לנו בונה משתמש מדומה נוח והטמעה בזיכרון של שירות פרטי המשתמש:

@Bean ציבור MapReactiveUserDetailsService userDetailsService () {UserDetails user = User .withUsername ("user"). Password (passwordEncoder (). Encode ("password")) .roles ("USER") .build (); להחזיר MapReactiveUserDetailsService חדש (משתמש); }

מכיוון שאנו נמצאים בארץ תגובתי, שירות פרטי המשתמש צריך להיות גם תגובתי. אם נבדוק את ReactiveUserDetailsService מִמְשָׁק, נראה שזה שלה findByUsername שיטה למעשה מחזירה א מונו מוֹצִיא לָאוֹר:

ממשק ציבורי ReactiveUserDetailsService {מונו findByUsername (שם משתמש מחרוזת); }

כעת אנו יכולים להריץ את היישום שלנו ולצפות בטופס אימות בסיסי רגיל של HTTP.

4. טופס התחברות מעוצב

שיפור קטן אך בולט ב- Spring Security 5 הוא טופס כניסה חדש ומעוצב המשתמש במסגרת Bootstrap 4 CSS. גיליונות הסגנון בטופס ההתחברות מקשרים ל- CDN, כך שנראה את השיפור רק בחיבור לאינטרנט.

כדי להשתמש בטופס הכניסה החדש, בואו נוסיף את התואם formLogin () שיטת בונה ל ServerHttpSecurity בּוֹנֶה:

אבטחה ציבוריתWebFilterChain securitygWebFilterChain (ServerHttpSecurity http) {return http.authorizeExchange () .anyExchange (). מאומת () .and (). formLogin () .and (). build (); }

אם נפתח כעת את הדף הראשי של היישום, נראה שהוא נראה הרבה יותר טוב מאשר טופס ברירת המחדל שהיינו רגילים אליו מאז הגרסאות הקודמות של Spring Security:

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

אם נכנס כעת ואז נעבור לכתובת URL // localhost: 8080 / יציאה, נראה את טופס אישור ההתנתקות, שגם הוא מעוצב.

5. אבטחת בקר תגובתי

כדי לראות משהו מאחורי טופס האימות, בואו נשתמש בבקר תגובתי פשוט המברך את המשתמש:

@RestController מחלקה ציבורית GreetController {@GetMapping ("/") ברכת מונו ציבורית (מנהל מונו) {return .map (ראשי :: getName) .map (שם -> String.format ("שלום,% s", שם) ); }}

לאחר הכניסה, נראה את הברכה. בואו נוסיף מטפל תגובתי נוסף שיהיה נגיש על ידי מנהל המערכת בלבד:

@GetMapping ("/ admin") Mono greetAdmin ציבורי (מונו מנהל) {return principal .map (Principal :: getName) .map (name -> String.format ("Admin access:% s", name)); }

עכשיו בואו ניצור משתמש שני עם התפקיד מנהל: בשירות פרטי המשתמש שלנו:

UserDetails admin = User.withDefaultPasswordEncoder (). Username ("admin"). Password ("password") .roles ("ADMIN") .build ();

כעת אנו יכולים להוסיף כלל התאמה לכתובת ה- URL לניהול שדורש מהמשתמש להיות בעל ה- ROLE_ADMIN רָשׁוּת.

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

להחזיר http.authorizeExchange () .pathMatchers ("/ admin"). hasAuthority ("ROLE_ADMIN") .anyExchange (). מאומת () .and (). formLogin () .and (). build ();

אם עכשיו נכנס עם מִשׁתַמֵשׁ אוֹ מנהל, נראה ששניהם מקיימים ברכה ראשונית, מכיוון שהנגשנו אותה לכל המשתמשים המאומתים.

אבל רק ה מנהל המשתמש יכול ללכת לכתובת האתר // localhost: 8080 / admin ולראות את ברכתה.

6. אבטחת שיטות תגובתיות

ראינו כיצד נוכל לאבטח את כתובות האתרים, אך מה לגבי שיטות?

כדי לאפשר אבטחה מבוססת-שיטה לשיטות תגובתיות, עלינו רק להוסיף את ה- @EnableReactiveMethodSecurity ביאור שלנו אבטחהקונפיג מעמד:

@EnableWebFluxSecurity @EnableReactiveMethodSecurity מחלקה ציבורית SecurityConfig {// ...}

עכשיו בואו ניצור שירות ברכה תגובתי עם התוכן הבא:

@Service בכיתה ציבורית GreetService {ברכה מונו ציבורית () {להחזיר Mono.just ("שלום מהשירות!"); }}

אנו יכולים להזרים אותו לבקר, לעבור אל // localhost: 8080 / greetService ולראות שזה אכן עובד:

@RestController מחלקה ציבורית GreetController {private GreetService greetService @GetMapping ("/ greetService") mono greetService ציבורי () {return greetService.greet (); } // קונסטרוקציות סטנדרטיות ...}

אבל אם נוסיף כעת את @ PreAuthorize ביאור על שיטת השירות עם מנהל תפקיד, אז כתובת ה- URL של שירות הברכה לא תהיה נגישה למשתמש רגיל:

@Service בכיתה ציבורית GreetService {@PreAuthorize ("hasRole ('ADMIN')") ברכת מונו ציבורית () {// ...}

7. ללעג למשתמשים בבדיקות

בואו לבדוק כמה קל לבדוק את יישום האביב התגובתי שלנו.

ראשית, ניצור בדיקה עם הקשר יישום מוזרק:

@ContextConfiguration (class = SpringSecurity5Application.class) מחלקה ציבורית SecurityTest {@Autowired ApplicationContext context; // ...}

כעת נקים לקוח בדיקת אתרים תגובתי פשוט, המהווה תכונה של מסגרת הבדיקה באביב 5:

@ לפני התקנת הריק הציבורי () {this.rest = WebTestClient .bindToApplicationContext (this.context) .configureClient () .build (); }

זה מאפשר לנו לבדוק במהירות שהמשתמש הלא מורשה מנותב מהדף הראשי של היישום שלנו לדף הכניסה:

@ מבחן ציבורי בטל כאשר NoCredentials_thenRedirectToLogin () {this.rest.get () .uri ("/"). Exchange () .expectStatus (). Is3xxRedirection (); }

אם כעת נוסיף את @MockWithUser ביאור לשיטת בדיקה, אנו יכולים לספק משתמש מאומת לשיטה זו.

הכניסה והסיסמה של משתמש זה יהיו מִשׁתַמֵשׁ ו סיסמה בהתאמה, והתפקיד הוא מִשׁתַמֵשׁ. את זה, כמובן, ניתן להגדיר עם ה- @MockWithUser פרמטרים של ביאור.

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

@Test @WithMockUser בטל בציבור כאשר HasCredentials_thenSeesGreeting () {this.rest.get () .uri ("/"). Exchange () .expectStatus (). IsOk () .expectBody (String.class) .isEqualTo ("שלום, משתמש "); }

ה @WithMockUser ביאור זמין מאז אבטחת האביב 4. עם זאת, באביב אבטחה 5 הוא עודכן גם בכדי לכסות נקודות קצה ושיטות תגובתיות.

8. מסקנה

במדריך זה גילינו תכונות חדשות של מהדורת Spring Security 5 הקרובה, במיוחד בזירת התכנות התגובתית.

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


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