דף כניסה לאבטחה באביב עם זוויתית

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

במדריך זה, ניצור דף כניסה באמצעות Spring Security עם:

  • AngularJS
  • זוויתית 2, 4, 5 ו -6

יישום הדוגמה שעליו נדון כאן מורכב מיישום לקוח שמתקשר עם שירות ה- REST, מאובטח באימות HTTP בסיסי.

2. תצורת אבטחה באביב

קודם כל, בואו נקבע את ה- REST API עם Spring Security ו- Auth Basic:

כך היא מוגדרת:

@Configuration @EnableWebSecurity המחלקה הציבורית BasicAuthConfiguration מרחיב את WebSecurityConfigurerAdapter {@Override מוגן חלל להגדיר (AuthenticationManagerBuilder auth) זורק חריג {auth .inMemoryAuthentication () .withUser ("משתמש"). סיסמה ("סיסמה") .roles. } התצורה הריקה המוגנת על ידי @Override (HttpSecurity http) זורקת חריג {http.csrf (). השבת () .authorizeRequests () .antMatchers ("/ login"). PermAll () .anyRequest (). מאומת () .and () .httpBasic (); }}

עכשיו בואו ניצור את נקודות הקצה. לשירות ה- REST שלנו יהיו שניים - אחד לכניסה והשני לאיסוף נתוני המשתמש:

@RestController @CrossOrigin מחלקת ציבור UserController {@RequestMapping ("/ login") כניסה בוליאנית ציבורית (משתמש משתמש @RequestBody) {return user.getUserName (). שווה ("user") && user.getPassword (). שווה ("סיסמה "); } @RequestMapping ("/ user") משתמש ראשי ציבורי (HttpServletRequest בקשה) {String authToken = request.getHeader ("Authorization"). Substring ("Basic" .length ()). Trim (); return () -> מחרוזת חדשה (Base64.getDecoder () .decode (authToken)). split (":") [0]; }}

כמו כן, תוכלו לעיין במדריך הנוסף שלנו בנושא Spring Security OAuth2 גם אם אתם מעוניינים ליישם שרת OAuth2 לצורך הרשאה.

3. הגדרת הלקוח הזוויתי

כעת לאחר שיצרנו את שירות ה- REST, נקבע את דף הכניסה עם גרסאות שונות של לקוח Angular.

הדוגמאות שנראה כאן עושות שימוש npm לניהול תלות ו nodejs להפעלת היישום.

Angular משתמשת בארכיטקטורת עמודים בודדת שבה כל רכיבי הצאצא (במקרה שלנו מדובר ברכיבי כניסה ובית) מוזרקים לדום הורים משותף.

בניגוד ל- AngularJS, המשתמשת ב- JavaScript, גרסה Angular 2 ואילך משתמשת ב- TypeScript כשפה העיקרית שלה. מכאן שהיישום דורש גם קבצי תמיכה מסוימים הנחוצים בכדי שהוא יעבוד כראוי.

בשל השיפורים המצטברים של Angular, הקבצים הדרושים שונים מגרסה לגרסה.

בואו נכיר את כל אלה:

  • systemjs.config.js - תצורות מערכת (גרסה 2)
  • package.json - תלות במודול הצומת (גרסה 2 ואילך)
  • tsconfig.json - תצורות טיפוסי כתב ברמת השורש (גרסה 2 ואילך)
  • tsconfig.app.json - תצורות טיפוסיות ברמת היישום (גרסה 4 ואילך)
  • .אנגולרית-קלי.json - תצורות CLI זוויתיות (גרסה 4 ו -5)
  • angular.json - תצורות CLI זוויתיות (גרסה 6 ואילך)

4. דף כניסה

4.1. שימוש ב- AngularJS

בואו ניצור את index.html הקובץ והוסף אליו את התלות הרלוונטית:

מכיוון שמדובר ביישום עמוד בודד, כל רכיבי הצאצא יתווספו לאלמנט div עם ng-view תכונה המבוססת על לוגיקת הניתוב.

עכשיו בואו ניצור את app.js המגדיר את כתובת האתר למיפוי רכיבים:

(function () {'use strict';. זוויתי. module ('app', ['ngRoute']) .config (config). run (run); config. $ inject = ['$ routeProvider', '$ locationProvider' ]; פונקציית תצורה ($ routeProvider, $ locationProvider) {$ routeProvider.when ('/', {controller: 'HomeController', templateUrl: 'home / home.view.html', controllerAs: 'vm'}). מתי ( '/ login', {controller: 'LoginController', templateUrl: 'login / login.view.html', controllerAs: 'vm'}). אחרת ({redirectTo: '/ login'});} הפעל. $ inject = ['$ rootScope', '$ location', '$ http', '$ window']; הפעלת פונקציות ($ rootScope, $ location, $ http, $ window) {var userData = $ window.sessionStorage.getItem ('userData '); אם (userData) {$ http.defaults.headers.common [' Authorization '] =' בסיסי '+ JSON.parse (userData) .authData;} $ rootScope. $ ב- (' $ locationChangeStart ', פונקציה (אירוע) , הבא, הנוכחי) {var restrictedPage = $ .inArray ($ location.path (), ['/ login']) === -1; var LoginIn = $ window.sessionStorage.getItem ('userData'); אם ( restrictedPage &&! מחובר) {$ location.pat h ('/ כניסה'); }}); }}) ();

רכיב הכניסה מורכב משני קבצים, ה- login.controller.js, וה login.view.html.

בואו נסתכל על הראשון:

התחברות

שם משתמש נדרש שם משתמש סיסמה נדרשת כניסה

והשני:

(function () {'use strict';. זוויתית. module ('app') .controller ('LoginController', LoginController); LoginController. $ inject = ['$ location', '$ window', '$ http']; פונקציה LoginController ($ location, $ window, $ http) {var vm = this; vm.login = login; (function initController () {$ window.localStorage.setItem ('token', '');}) (); כניסה לפונקציה () {$ http ({url: '// localhost: 8082 / login', שיטה: "POST", נתונים: {'userName': vm.username, 'password': vm.password}}). (פונקציה (תגובה) {if (response.data) {var token = $ window.btoa (vm.username + ':' + vm.password); var userData = {userName: vm.username, authData: token} $ window .sessionStorage.setItem ('userData', JSON.stringify (userData)); $ http.defaults.headers.common ['Authorization'] = 'בסיסי' + אסימון; $ location.path ('/');} אחר { התראה ("האימות נכשל.")}})}}}}) ();

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

בדומה לרכיב הכניסה, הרכיב הביתי מורכב גם משני קבצים, ה- home.view.html:

אתה מחובר !!

להתנתק

וה home.controller.js:

(function () {'use strict'; זוויתי. module ('app') .controller ('HomeController', HomeController); HomeController. $ inject = ['$ window', '$ http', '$ scope']; פונקציה HomeController ($ חלון, $ http, $ היקף) {var vm = זה; vm.user = null; initController (); פונקציה initController () {$ http ({url: '// localhost: 8082 / user', שיטה : "GET"}). ואז (פונקציה (תגובה) {vm.user = respons.data.name;}, פונקציה (שגיאה) {console.log (שגיאה);});}; $ scope.logout = פונקציה ( ) {$ window.sessionStorage.setItem ('userData', ''); $ http.defaults.headers.common ['Authorization'] = 'בסיסי';}}}) ();

בקר הבית יבקש את נתוני המשתמש על ידי העברת ה- הרשאה כּוֹתֶרֶת. שירות ה- REST שלנו יחזיר את נתוני המשתמש רק אם האסימון תקף.

עכשיו בואו להתקין שרת http להפעלת יישום Angular:

npm להתקין שרת http - שמור

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

שרת http -או

4.2. באמצעות גרסה זוויתית 2, 4, 5

ה index.html בגרסה 2 שונה מעט מגרסת AngularJS:

         System.import ('אפליקציה'). לתפוס (פונקציה (err) {console.error (err);}); טוען... 

ה main.ts היא נקודת הכניסה העיקרית של היישום. הוא מאתחל את מודול היישום וכתוצאה מכך, הדפדפן טוען את דף הכניסה:

platformBrowserDynamic (). bootstrapModule (AppModule);

ה app.routing.ts אחראי על ניתוב היישומים:

const appRoutes: Routes = [{path: '', component: HomeComponent}, {path: 'login', component: LoginComponent}, {path: '**', redirectTo: ''}]; ניתוב קונסט ניתוב = RouterModule.forRoot (appRoutes);

ה app.module.ts מצהיר על הרכיבים ומייבא את המודולים הרלוונטיים:

@NgModule ({יבוא: [BrowserModule, FormsModule, HttpModule, ניתוב], הצהרות: [AppComponent, HomeComponent, LoginComponent], bootstrap: [AppComponent]}) ייצוא מחלקה AppModule {}

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

@Component ({selector: 'app-root', templateUrl: './app.component.html'}) מחלקת ייצוא AppComponent {}

ה app.component.html יהיה רק ​​א תָג. ה- Angular משתמש בתגית זו עבור מנגנון ניתוב המיקום שלה.

עכשיו בואו ניצור את רכיב הכניסה ואת התבנית המתאימה שלו ב- login.component.ts:

@Component ({selector: 'login', templateUrl: './app/login/login.component.html'}) מחלקת ייצוא LoginComponent מיישמת OnInit {model: any = {}; קונסטרוקטור (מסלול פרטי: ActivatedRoute, נתב פרטי: נתב, פרטי http: Http) {} ngOnInit () {sessionStorage.setItem ('אסימון', ''); } התחבר () {let url = '// localhost: 8082 / login'; let result = this.http.post (url, {userName: this.model.username, password: this.model.password}). map (res => res.json ()). subscribe (isValid => {if ( isValid) {sessionStorage.setItem ('אסימון', btoa (this.model.username + ':' + this.model.password)); this.router.navigate (['']);} אחר {alert ("אימות נכשל. ");}}); }}

לבסוף, בואו נסתכל על ה- login.component.html:

 שם משתמש נדרש שם משתמש סיסמה נדרשת כניסה 

4.3. שימוש בזווית 6

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

במקום HttpModule, הגרסה 6 מייבאת HttpClientModule מ@ זוויתי / משותף / http.

החלק של קריאת השירות יהיה גם קצת שונה מגרסאות ישנות יותר:

this.http.post(url, {userName: this.model.username, password: this.model.password}). הירשם כמנוי (isValid => {if (isValid) {sessionStorage.setItem ('token', btoa (this.model.username + ') : '+ this.model.password)); this.router.navigate ([' ']);} אחר {alert ("אימות נכשל.")}});

5. מסקנה

למדנו כיצד ליישם דף כניסה של Spring Security עם Angular. החל מגרסה 4 ואילך, אנו יכולים להשתמש בפרויקט Angular CLI לפיתוח ובדיקה קלים.

כמו תמיד ניתן למצוא את כל הדוגמאות שדנו כאן בפרויקט GitHub.