Forårsikkerhed Login side med kantet

1. Oversigt

I denne vejledning opretter vi en login side ved hjælp af Spring Security med:

  • AngularJS
  • Vinkel 2, 4, 5 og 6

Eksempelapplikationen, som vi skal diskutere her, består af en klientapplikation, der kommunikerer med REST-tjenesten, sikret med grundlæggende HTTP-godkendelse.

2. Forårssikkerhedskonfiguration

Lad os først og fremmest oprette REST API med Spring Security og Basic Auth:

Sådan konfigureres det:

@Configuration @EnableWebSecurity offentlig klasse BasicAuthConfiguration udvider WebSecurityConfigurerAdapter {@Override beskyttet ugyldig konfiguration (AuthenticationManagerBuilder auth) kaster Undtagelse {auth .inMemoryAuthentication () .withUser ("bruger") .password ("password US)") .roles. } @ Override beskyttet ugyldig konfiguration (HttpSecurity http) kaster undtagelse {http.csrf (). Deaktiver () .authorizeRequests () .antMatchers ("/ login"). PermitAll () .anyRequest (). Godkendt (). Og () .httpBasic (); }}

Lad os nu oprette slutpunkterne. Vores REST-tjeneste har to - en til login og den anden til at hente brugerdata:

@RestController @CrossOrigin offentlig klasse UserController {@RequestMapping ("/ login") offentlig boolsk login (@RequestBody brugerbruger) {return user.getUserName (). Er lig med ("user") && user.getPassword (). Lig med ("password "); } @RequestMapping ("/ bruger") offentlig Hovedbruger (HttpServletRequest anmodning) {String authToken = request.getHeader ("Authorization"). Substring ("Basic" .length ()). Trim (); returnere () -> ny streng (Base64.getDecoder () .decode (authToken)). split (":") [0]; }}

På samme måde kan du også tjekke vores anden vejledning om Spring Security OAuth2, hvis du er interesseret i at implementere en OAuth2-server til godkendelse.

3. Opsætning af den kantede klient

Nu hvor vi har oprettet REST-tjenesten, lad os oprette login-siden med forskellige versioner af Angular-klienten.

Eksemplerne, som vi vil se her, bruger npm for afhængighedsstyring og nodejs til at køre applikationen.

Angular bruger en enkelt sidearkitektur, hvor alle underordnede komponenter (i vores tilfælde er dette login- og hjemmekomponenter) indsprøjtes i en fælles overordnet DOM.

I modsætning til AngularJS, som bruger JavaScript, bruger Angular version 2 og videre TypeScript som hovedsprog. Derfor kræver applikationen også visse understøttende filer, der er nødvendige for at den fungerer korrekt.

På grund af de inkrementelle forbedringer af Angular adskiller de nødvendige filer sig fra version til version.

Lad os blive fortrolige med hver af disse:

  • systemjs.config.js - systemkonfigurationer (version 2)
  • pakke.json - knudepunktsmodulafhængigheder (version 2 og fremefter)
  • tsconfig.json - rodniveau Typescript-konfigurationer (version 2 og senere)
  • tsconfig.app.json - applikationsniveau Typescript-konfigurationer (version 4 og senere)
  • .vinkel-cli.json - Vinkelformede CLI-konfigurationer (version 4 og 5)
  • vinkel.json - Vinkelformede CLI-konfigurationer (version 6 og fremefter)

4. Login side

4.1. Brug af AngularJS

Lad os oprette index.html fil og tilføj de relevante afhængigheder til den:

Da dette er en applikation til en enkelt side, tilføjes alle underordnede komponenter til div-elementet med ng-view attribut baseret på routinglogikken.

Lad os nu oprette app.js der definerer URL til komponentkortlægning:

(funktion () {'brug streng'; kantet .module ('app', ['ngRoute']) .config (config). run (run); config. $ inject = ['$ routeProvider', '$ locationProvider' ]; funktionskonfiguration ($ routeProvider, $ locationProvider) {$ routeProvider.when ('/', {controller: 'HomeController', templateUrl: 'home / home.view.html', controllerAs: 'vm'}). når ( '/ login', {controller: 'LoginController', templateUrl: 'login / login.view.html', controllerAs: 'vm'}). ellers ({redirectTo: '/ login'});} kør. $ inject = ['$ rootScope', '$ location', '$ http', '$ window']; function run ($ rootScope, $ location, $ http, $ window) {var userData = $ window.sessionStorage.getItem ('userData '); hvis (userData) {$ http.defaults.headers.common [' Authorization '] =' Basic '+ JSON.parse (userData) .authData;} $ rootScope. $ on (' $ locationChangeStart ', funktion (begivenhed) , næste, aktuelle) {var restrictedPage = $ .inArray ($ location.path (), ['/ login']) === -1; var loginIn = $ window.sessionStorage.getItem ('userData'); hvis ( restrictedPage &&! loginIn) {$ location.pat h ('/ login'); }}); }}) ();

Login-komponenten består af to filer, login.controller.js, og login.view.html.

Lad os se på den første:

Log på

Brugernavn Brugernavn er påkrævet Adgangskode Adgangskode kræves Login

og den anden:

(funktion () {'brug streng'; kantet .module ('app') .controller ('LoginController', LoginController); LoginController. $ inject = ['$ location', '$ window', '$ http']; funktion LoginController ($ placering, $ vindue, $ http) {var vm = dette; vm.login = login; (funktion initController () {$ window.localStorage.setItem ('token', '');}) (); funktions login () {$ http ({url: '// localhost: 8082 / login', metode: "POST", data: {'brugernavn': vm.username, 'password': vm.password}}). derefter. (funktion (svar) {if (respons.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'] = 'Grundlæggende' + token; $ location.path ('/');} andet { alarm ("Godkendelse mislykkedes.")}});};}}) ();

Controlleren vil påkalde REST-tjenesten ved at videregive brugernavnet og adgangskoden. Efter den vellykkede godkendelse koder det brugernavnet og adgangskoden og gemmer det kodede token i sessionlager til fremtidig brug.

I lighed med login-komponenten består hjemmekomponenten også af to filer, home.view.html:

Du er logget ind !!

Log ud

og home.controller.js:

(funktion () {'brug streng'; kantet .module ('app') .controller ('HomeController', HomeController); HomeController. $ inject = ['$ window', '$ http', '$ scope']; funktion HomeController ($ vindue, $ http, $ scope) {var vm = dette; vm.user = null; initController (); funktion initController () {$ http ({url: '// localhost: 8082 / bruger', metode : "GET"}). Derefter (funktion (respons) {vm.user = respons.data.navn;}, funktion (fejl) {konsol.log (fejl);});}; $ scope.logout = funktion ( ) {$ window.sessionStorage.setItem ('userData', ''); $ http.defaults.headers.common ['Authorization'] = 'Grundlæggende';}}}) ();

Hjemmecontrolleren vil anmode om brugerdata ved at videregive Bemyndigelse header. Vores REST-tjeneste returnerer kun brugerdataene, hvis tokenet er gyldigt.

Lad os nu installere http-server til kørsel af Angular-applikationen:

npm installer http-server --save

Når dette er installeret, kan vi åbne projektets rodmappe i kommandoprompten og udføre kommandoen:

http-server -o

4.2. Brug af vinkelversion 2, 4, 5

Det index.html i version 2 adskiller sig lidt fra AngularJS-versionen:

         System.import ('app'). Fangst (funktion (err) {console.error (err);}); Indlæser... 

Det main.ts er applikationens vigtigste indgangssted. Det bootstrapper applikationsmodulet og som et resultat indlæser browseren login-siden:

platformBrowserDynamic (). bootstrapModule (AppModule);

Det app.routing.ts er ansvarlig for applikationsrutingen:

const appRoutes: Routes = [{path: '', component: HomeComponent}, {path: 'login', component: LoginComponent}, {path: '**', redirectTo: ''}]; eksport const routing = RouterModule.forRoot (appRoutes);

Det app.module.ts erklærer komponenterne og importerer de relevante moduler:

@NgModule ({importerer: [BrowserModule, FormsModule, HttpModule, routing], erklæringer: [AppComponent, HomeComponent, LoginComponent], bootstrap: [AppComponent]}) eksportklasse AppModule {}

Da vi opretter en enkelt sideapplikation, skal vi oprette en rodkomponent, der føjer alle de underordnede komponenter til den:

@Component ({selector: 'app-root', templateUrl: './app.component.html'}) eksportklasse AppComponent {}

Det app.component.html vil kun have en tag. The Angular bruger dette mærke til sin lokaliseringsmekanisme.

Lad os nu oprette login-komponenten og dens tilsvarende skabelon i login.component.ts:

@Component ({selector: 'login', templateUrl: './app/login/login.component.html'}) eksportklasse LoginComponent implementerer OnInit {model: any = {}; konstruktør (privat rute: ActivatedRoute, privat router: Router, privat http: Http) {} ngOnInit () {sessionStorage.setItem ('token', ''); } login () {let url = '// localhost: 8082 / login'; lad resultat = dette.http.post (url, {brugernavn: dette.model.brugernavn, adgangskode: dette.model.password}). kort (res => res.json ()). abonner (isValid => {hvis ( isValid) {sessionStorage.setItem ('token', btoa (this.model.username + ':' + this.model.password)); this.router.navigate (['']);} ellers {alarm ("Authentication mislykkedes."); } }); }}

Lad os endelig se på login.komponent.html:

 Brugernavn Brugernavn kræves Kodeord Adgangskode kræves Login 

4.3. Brug af vinkel 6

Angular team har foretaget nogle forbedringer i version 6. På grund af disse ændringer vil vores eksempel også være lidt anderledes sammenlignet med andre versioner. Den eneste ændring, vi har i vores eksempel med hensyn til version 6, er i serviceopkaldsdelen.

I stedet for HttpModule, version 6 importerer HttpClientModule fra@ vinkel / fælles / http.

Serviceopkaldsdelen vil også være lidt anderledes end ældre versioner:

denne.http.post(url, {userName: this.model.username, password: this.model.password}). subscribe (isValid => {if (isValid) {sessionStorage.setItem ('token', btoa (this.model.username + ') : '+ dette.model.password)); dette.router.navigate ([' ']);} ellers {alarm ("Godkendelse mislykkedes.")}});

5. Konklusion

Vi har lært, hvordan man implementerer en Spring Security login-side med Angular. Fra og med version 4 kan vi bruge Angular CLI-projektet til nem udvikling og test.

Som altid kan alt det eksempel, vi har diskuteret her, findes over GitHub-projektet.


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