Proljetna sigurnosna stranica za prijavu s Reactom

1. Pregled

React je JavaScript biblioteka temeljena na komponentama koju je izradio Facebook. React omogućuje s lakoćom izradu složenih web aplikacija. U ovom ćemo članku učiniti da Spring Security radi zajedno sa stranicom React Login.

Iskoristit ćemo postojeće konfiguracije Spring Security iz prethodnih primjera. Stoga ćemo se nadovezati na prethodni članak o stvaranju prijave za obrazac s Spring Security.

2. Postavite React

Prvo, krenimo upotrijebite alat naredbenog retka create-response-app za izradu aplikacije izvršavanjem naredbe “stvoriti-reagirati-aplikacija reagirati ".

Imat ćemo konfiguraciju poput sljedeće u reagirati / paket.json:

{"ime": "reagiraj", "verzija": "0.1.0", "privatno": istina, "ovisnosti": {"reagiraj": "^ 16.4.1", "reagiraj-dom": "^ 16.4 .1 "," response-scripts ":" 1.1.4 "}," scripts ": {" start ":" response-scripts start "," build ":" response-scripts build "," test ":" reagirajte -scripts test --env = jsdom "," eject ":" response-scripts eject "}}

Onda ćemo upotrijebite dodatak frontend-maven za pomoć u izradi našeg React projekta s Mavenom:

 com.github.eirslett frontend-maven-plugin 1.6 v8.11.3 6.1.0 src / main / webapp / WEB-INF / view / React install node i npm install-node-and-npm npm install npm npm run build npm run build 

Najnoviju verziju dodatka možete pronaći ovdje.

Kad trčimo mvn sastaviti, ovaj dodatak će se preuzeti čvor i npm, instalirajte sve ovisnosti modula čvora i izgradite projekt reagiranja za nas.

Ovdje moramo objasniti nekoliko svojstava konfiguracije. Naveli smo verzije čvor i npm, tako da će dodatak znati koju verziju preuzeti.

Naša stranica za prijavu React poslužit će kao statična stranica na proljeće, pa koristimo "src / glavna /webapp/ WEB-INF / pregledaj / reagiraj”Kao npm'Radni direktorij.

3. Proljetna sigurnosna konfiguracija

Prije nego što zaronimo u komponente React, ažuriramo konfiguraciju Spring kako bi poslužili statičkim resursima naše aplikacije React:

@EnableWebMvc @Configuration javna klasa MvcConfig proširuje WebMvcConfigurerAdapter {@Override javna void addResourceHandlers (ResourceHandlerRegistry registar) {registry.addResourceHandler ("/ static / **") / add / Resurs / IN / ); registry.addResourceHandler ("/ *. js") .addResourceLocations ("/ WEB-INF / view / response / build /"); registry.addResourceHandler ("/ *. json") .addResourceLocations ("/ WEB-INF / view / response / build /"); registry.addResourceHandler ("/ *. ico") .addResourceLocations ("/ WEB-INF / view / response / build /"); registry.addResourceHandler ("/ index.html") .addResourceLocations ("/ WEB-INF / view / response / build / index.html"); }}

Imajte na umu da dodajemo stranicu za prijavu "Index.html" kao statički resurs umjesto dinamički posluženog JSP-a.

Dalje, ažuriramo konfiguraciju Spring Security kako bismo omogućili pristup tim statičkim resursima.

Umjesto da koristi "Login.jsp" kao što smo to učinili u prethodnom članku o prijavi, ovdje koristimo "Index.html" kao naš Prijaviti se stranica:

@Configuration @EnableWebSecurity @Profile ("! Https") javna klasa SecSecurityConfig proširuje WebSecurityConfigurerAdapter {// ... @Override zaštićena void konfiguracija (konačni HttpSecurity http) baca izuzetak {http.csrf (). Disable (). AuthzeRequests. / ... .antMatchers (HttpMethod.GET, "/ index *", "/ static / **", "/*.js", "/*.json", "/*.ico") .permitAll () .anyRequest (). authenticated () .and () .formLogin (). loginPage ("/ index.html") .loginProcessingUrl ("/ perform_login") .defaultSuccessUrl ("/ homepage.html", true) .failureUrl (" /index.html?error=true ") // ...}}

Kao što možemo vidjeti iz gornjeg isječka kada podatke obrasca objavimo u “/ izvesti_login“, Proljeće će nas preusmjeriti na“/homepage.html"Ako se vjerodajnice uspješno podudaraju i na"/index.html?error=true”Inače.

4. Reagirajuće komponente

A sad, uprljajmo ruke na Reactu. Izgradit ćemo i upravljati prijavom za obrazac pomoću komponenata.

Napominjemo da ćemo za izradu naše aplikacije koristiti sintaksu ES6 (ECMAScript 2015).

4.1. Ulazni

Počnimo s Ulazni komponenta koja podupire elementi obrasca za prijavu u reagirati / src / Input.js:

import React, {Component} iz 'reagiraj' import PropTypes iz klase 'prop-types' Ulaz proširuje komponentu {konstruktor (rekviziti) {super (rekviziti) this.state = {value: props.value? props.value: '', ime klase: props.className? props.className: '', error: false}} // ... render () {const {handleError, ... opts} = this.props this.handleError = handleError return ()}} Input.propTypes = {name : PropTypes.string, rezervirano mjesto: PropTypes.string, tip: PropTypes.string, className: PropTypes.string, vrijednost: PropTypes.string, handleError: PropTypes.func} izvoz zadani ulaz

Kao što se vidi gore, omotamo element u React kontroliranu komponentu kako bi mogao upravljati svojim stanjem i vršiti provjeru polja.

React pruža način provjere valjanosti tipova pomoću PropTypes. Konkretno, koristimo Input.propTypes = {…} za provjeru vrste svojstava koja je korisnik predao.

Imajte na umu da PropType provjera valjanosti radi samo za razvoj. PropType provjera valjanosti je provjeravanje jesu li ispunjene sve pretpostavke koje donosimo o našim komponentama.

Bolje ga je imati, a ne iznenaditi slučajnim štucanjem u proizvodnji.

4.2. Oblik

Dalje ćemo u datoteci izgraditi generičku komponentu obrasca Form.js koji kombinira višestruke primjere našeg Ulazni komponenta na kojoj možemo temeljiti svoj obrazac za prijavu.

U Oblik komponentu, uzimamo atribute HTML-a elemente i stvarati Ulazni komponente od njih.

Onda Ulazni komponente i poruke o pogrešci provjere valjanosti unose se u Oblik:

import React, {Component} iz 'response' import PropTypes from 'prop-types' import Input from './Input' class Obrazac proširuje Component {// ... render () {const inputs = this.props.inputs.map (({ime, rezervirano mjesto, vrsta, vrijednost, ime klase}, indeks) => ()) pogreške const = this.renderError () return ({this.form = fm}}> {inputs} {pogreške})}} Obrazac .propTypes = {ime: PropTypes.string, akcija: PropTypes.string, metoda: PropTypes.string, unosi: PropTypes.array, pogreška: PropTypes.string} izvoz zadani obrazac

Sada pogledajmo kako upravljamo pogreškama provjere valjanosti polja i pogreškom prijave:

klasa Obrazac proširuje komponentu {konstruktor (rekviziti) {super (rekviziti) ako (props.error) {this.state = {neuspjeh: 'pogrešno korisničko ime ili lozinka!', errcount: 0}} else {this.state = {errcount: 0}}} handleError = (field, errmsg) => {if (! Field) return if (errmsg) {this.setState ((prevState) => ({neuspjeh: '', broj pogrešaka: prevState.errcount + 1, errmsgs : {... prevState.errmsgs, [field]: errmsg}}))} else {this.setState ((prevState) => ({neuspjeh: '', errcount: prevState.errcount === 1? 0: prevState .errcount-1, errmsgs: {... prevState.errmsgs, [polje]: ''}}))}} renderError = () => {if (this.state.errcount || this.state.failure) { const errmsg = this.state.filure || Object.values ​​(this.state.errmsgs) .find (v => v) return {errmsg}}} // ...}

U ovom isječku definiramo handleError funkcija za upravljanje stanjem pogreške obrasca. Podsjetimo da smo ga također koristili za Ulazni provjera polja. Zapravo, handleError () se prosljeđuje Ulazne komponente kao povratni poziv u prikazati () funkcija.

Koristimo renderError () za konstrukciju elementa poruke o pogrešci. Imajte na umu da Obrasci konstruktor troši an pogreška imovine. Ovo svojstvo pokazuje ako akcija prijave ne uspije.

Zatim dolazi rukovatelj predajom obrasca:

klasa Obrazac proširuje komponentu {// ... handleSubmit = (događaj) => {event.preventDefault () if (! this.state.errcount) {const data = new FormData (this.form) dohvaćanje (this.form.action , {metoda: this.form.method, body: new URLSearchParams (data)}). then (v => {if (v.redirected) window.location = v.url}) .catch (e => console.warn (e))}}}

Obmotavamo sva polja obrasca FormData i pošaljite ga poslužitelju pomoću donijeti API.

Ne zaboravimo da se uz obrazac za prijavu dolazi i uspjehUrl i neuspjehUrl, što znači da će bez obzira je li zahtjev uspješan ili ne, odgovor zahtijevati preusmjeravanje.

Zbog toga se moramo nositi s preusmjeravanjem u odgovoru povratnog poziva.

4.3. Prikazivanje obrazaca

Sad kad smo postavili sve potrebne komponente, možemo ih nastaviti stavljati u DOM. Osnovna HTML struktura je sljedeća (pronađite je pod reagirati / public / index.html):

Napokon ćemo obrazac prikazati u s id-om “kontejner ” u reagirati / src / index.js:

uvoz React iz 'reagiraj' import ReactDOM iz 'response-dom' import './index.css' obrazac za uvoz iz './Form' const inputs = [{name: "username", rezervirano mjesto: "username", type: " text "}, {name:" password ", rezervirano mjesto:" password ", type:" password "}, {type:" submit ", value:" Submit ", className:" btn "}] const props = {name: 'loginForm', metoda: 'POST', radnja: '/ perform_login', inputs: inputs} const params = new URLSearchParams (window.location.search) ReactDOM.render (, document.getElementById ('container'))

Dakle, naš obrazac sada sadrži dva polja za unos: Korisničko ime i zaporkai gumb za slanje.

Ovdje prolazimo dodatni pogreška atribut Oblik komponentu jer želimo obraditi pogrešku prilikom prijave nakon preusmjeravanja na URL neuspjeha: /index.html?error=true.

Sada smo završili s izradom prijave za prijavu Spring Securitya pomoću React-a. Posljednje što moramo učiniti je trčati mvn sastaviti.

Tijekom postupka dodatak Maven pomoći će u izradi naše React aplikacije i prikupljanju rezultata gradnje u src / main / webapp / WEB-INF / view / response / build.

5. Zaključak

U ovom smo članku opisali kako izraditi aplikaciju za prijavu React i omogućiti joj interakciju s pozadinskom zaštitom Spring Security. Složenija aplikacija uključivala bi tranziciju stanja i usmjeravanje pomoću React Routera ili Redux-a, ali to bi bilo izvan dosega ovog članka.

Kao i uvijek, cjelovitu implementaciju možete pronaći na GitHubu. Da biste ga pokrenuli lokalno, izvršite mvn jetty: trči u korijenskoj mapi projekta, tada možemo pristupiti stranici za prijavu React na // localhost: 8080.