Påloggingsside for vårsikkerhet med React

1. Oversikt

React er et komponentbasert JavaScript-bibliotek bygget av Facebook. Med React kan vi enkelt bygge komplekse webapplikasjoner. I denne artikkelen skal vi få vårsikkerhet til å fungere sammen med en React Login-side.

Vi utnytter de eksisterende Spring Security-konfigurasjonene fra tidligere eksempler. Så vi vil bygge på toppen av en tidligere artikkel om å opprette en skjemainnlogging med Spring Security.

2. Sett opp Reager

Først, la oss bruk kommandolinjeverktøyet create-react-app for å opprette en applikasjon ved å utføre kommandoen “create-react-app react ”.

Vi har en konfigurasjon som følgende i reagere / pakke.json:

{"name": "react", "version": "0.1.0", "private": true, "dependencies": {"react": "^ 16.4.1", "react-dom": "^ 16.4 .1 "," react-scripts ":" 1.1.4 "}," scripts ": {" start ":" react-scripts start "," build ":" react-scripts build "," test ":" react -scripts test --env = jsdom "," eject ":" react-scripts eject "}}

Så skal vi bruk frontend-maven-plugin for å bygge React-prosjektet vårt med Maven:

 com.github.eirslett frontend-maven-plugin 1.6 v8.11.3 6.1.0 src / main / webapp / WEB-INF / view / react installere node og npm install-node-og-npm npm installere npm npm kjøre bygge npm kjøre bygge 

Den siste versjonen av pluginet finner du her.

Når vi løper mvn kompilere, dette pluginet lastes ned node og npm, installer alle avhengigheter av nodemodulen og bygg reageringsprosjektet for oss.

Det er flere konfigurasjonsegenskaper vi trenger å forklare her. Vi spesifiserte versjonene av node og npm, slik at pluginet vet hvilken versjon som skal lastes ned.

Vår React-påloggingsside vil fungere som en statisk side om våren, så vi bruker “src / main /webapp/ WEB-INF / vis / reager" som npm’S arbeidskatalog.

3. Vårs sikkerhetskonfigurasjon

Før vi dykker ned i React-komponentene, oppdaterer vi vårkonfigurasjonen for å betjene de statiske ressursene i React-appen vår:

@EnableWebMvc @Configuration public class MvcConfig utvider WebMvcConfigurerAdapter {@Override public void addResourceHandlers (ResourceHandlerRegistry registry) {registry.addResourceHandler ("/ static / **") .addResourceLocations ("/ WEB-INF / stat / / / / / ); registry.addResourceHandler ("/ *. js") .addResourceLocations ("/ WEB-INF / view / react / build /"); registry.addResourceHandler ("/ *. json") .addResourceLocations ("/ WEB-INF / view / react / build /"); registry.addResourceHandler ("/ *. ico") .addResourceLocations ("/ WEB-INF / view / react / build /"); registry.addResourceHandler ("/ index.html") .addResourceLocations ("/ WEB-INF / view / react / build / index.html"); }}

Merk at vi legger til påloggingssiden “Index.html” som en statisk ressurs i stedet for en dynamisk servert JSP.

Deretter oppdaterer vi Spring Security-konfigurasjonen for å gi tilgang til disse statiske ressursene.

I stedet for å bruke “Login.jsp” som vi gjorde i forrige skjemainnloggingsartikkel, her bruker vi “Index.html” som vår Logg Inn side:

@Configuration @EnableWebSecurity @Profile ("! Https") offentlig klasse SecSecurityConfig utvider WebSecurityConfigurerAdapter {// ... @Override-beskyttet tomkonfigurasjon (endelig HttpSecurity http) kaster Unntak {http.csrf (). Deaktiver (). AuthorizeRequests () / / ... .antMatchers (HttpMethod.GET, "/ index *", "/ static / **", "/*.js", "/*.json", "/*.ico") .permitAll () .anyRequest (). autentisert () .and () .formLogin (). loginPage ("/ index.html") .loginProcessingUrl ("/ perform_login") .defaultSuccessUrl ("/ homepage.html", true) .failureUrl (" /index.html?error=true ") // ...}}

Som vi kan se fra kodebiten ovenfor når vi legger ut skjemadata til “/ perform_login“, Våren vil omdirigere oss til“/hjemmeside.html”Hvis legitimasjonen stemmer overens og til“/index.html?error=tro" ellers.

4. Reager komponenter

La oss nå skitne hendene våre på React. Vi bygger og administrerer en skjemainnlogging ved hjelp av komponenter.

Merk at vi bruker ES6 (ECMAScript 2015) syntaks for å bygge applikasjonen vår.

4.1. Inngang

La oss starte med en Inngang komponent som støtter elementene i påloggingsskjemaet i reager / src / Input.js:

importer React, {Component} fra 'react' import PropTypes from 'prop-types' class Input extends Component {constructor (rekvisitter) {super (rekvisitter) this.state = {value: props.value? props.value: '', className: props.className? props.className: '', error: false}} // ... render () {const {handleError, ... opts} = this.props this.handleError = handleError return ()}} Input.propTypes = {name : PropTypes.string, plassholder: PropTypes.string, type: PropTypes.string, className: PropTypes.string, verdi: PropTypes.string, handleError: PropTypes.func} eksport standardinngang

Som vist ovenfor, pakker vi inn element i en React-kontrollert komponent for å kunne administrere tilstanden og utføre feltvalidering.

React gir en måte å validere typene ved hjelp av PropTypes. Spesielt bruker vi Input.propTypes = {…} for å validere typen eiendommer som sendes inn av brukeren.

Noter det PropType validering fungerer bare for utvikling. PropType validering er å sjekke at alle forutsetningene vi gjør om komponentene våre blir oppfylt.

Det er bedre å ha det i stedet for å bli overrasket over tilfeldige hikke i produksjonen.

4.2. Skjema

Deretter bygger vi en generell skjemakomponent i filen Form.js som kombinerer flere forekomster av vår Inngang komponent som vi kan basere påloggingsskjemaet vårt på.

I Skjema komponent, tar vi attributter av HTML elementer og skape Inngang komponenter fra dem.

Og så Inngang komponenter og validering feilmeldinger settes inn i Skjema:

importer React, {Component} fra 'react' import PropTypes from 'prop-types' import Input from './Input' class Form extends Component {// ... render () {const inputs = this.props.inputs.map (({navn, plassholder, type, verdi, className}, indeks) => ()) const feil = this.renderError () retur ({this.form = fm}}> {inputs} {feil})}} Form .propTypes = {name: PropTypes.string, action: PropTypes.string, method: PropTypes.string, inputs: PropTypes.array, error: PropTypes.string} export default Form

La oss nå se på hvordan vi håndterer feltvalideringsfeil og påloggingsfeil:

klasse Form utvider komponent {constructor (rekvisitter) {super (rekvisitter) hvis (props.error) {this.state = {failure: 'feil brukernavn eller passord!', errcount: 0}} annet {this.state = {errcount: 0}}} handleError = (field, errmsg) => {if (! Field) return hvis (errmsg) {this.setState ((prevState) => ({failure: '', errcount: prevState.errcount + 1, errmsgs) : {... prevState.errmsgs, [field]: errmsg}})}} annet {this.setState ((prevState) => ({failure: '', errcount: prevState.errcount === 1? 0: prevState .errcount-1, errmsgs: {... prevState.errmsgs, [field]: ''}})}} renderError = () => {if (this.state.errcount || this.state.failure) { const errmsg = this.state.failure || Object.values ​​(this.state.errmsgs) .find (v => v) returnerer {errmsg}}} // ...}

I dette utdraget definerer vi handleError funksjon for å håndtere skjemaets feiltilstand. Husk at vi også brukte den til Inngang feltvalidering. Faktisk, handleError () blir overført til Inngangskomponenter som tilbakeringing i gjengi () funksjon.

Vi bruker renderError () for å konstruere feilmeldingselementet. Noter det Form er konstruksjon forbruker en feil eiendom. Denne egenskapen indikerer om påloggingshandlingen mislykkes.

Så kommer skjemainnleveringsbehandleren:

klasse Form utvider komponent {// ... handleSubmit = (event) => {event.preventDefault () if (! this.state.errcount) {const data = new FormData (this.form) fetch (this.form.action , {method: this.form.method, body: new URLSearchParams (data)}) .then (v => {if (v.omdirigert) window.location = v.url}) .catch (e => console.warn (e))}}}

Vi pakker alle skjemafelt inn i FormData og send den til serveren ved hjelp av hente API.

La oss ikke glemme påloggingsskjemaet vårt kommer med et suksessUrl og feilUrl, noe som betyr at uansett om forespørselen er vellykket eller ikke, vil svaret kreve en omdirigering.

Derfor må vi håndtere omdirigering i tilbakeringingen.

4.3. Skjema gjengivelse

Nå som vi har satt opp alle komponentene vi trenger, kan vi fortsette å plassere dem i DOM. Den grunnleggende HTML-strukturen er som følger (finn den under react / public / index.html):

Til slutt gjengir vi skjemaet til med id “container" i reager / src / index.js:

import React from 'react' import ReactDOM from 'react-dom' import './index.css' import Form fra './Form' const inputs = [{name: "brukernavn", plassholder: "brukernavn", type: " tekst "}, {name:" password ", placeholder:" password ", type:" password "}, {type:" submit ", value:" Submit ", className:" btn "}] const props = {name: 'loginForm', metode: 'POST', handling: '/ perform_login', innganger: innganger} const params = ny URLSearchParams (window.location.search) ReactDOM.render (, document.getElementById ('container'))

Så skjemaet vårt inneholder nå to inndatafelt: brukernavn og passord, og en sendeknapp.

Her passerer vi en ekstra feil attributt til Skjema komponent fordi vi ønsker å håndtere påloggingsfeil etter omdirigering til feil URL: /index.html?error=sann.

Nå er vi ferdig med å bygge en Spring Security-påloggingsapplikasjon ved hjelp av React. Det siste vi må gjøre er å løpe mvn kompilere.

I løpet av prosessen vil Maven-pluginet bidra til å bygge React-applikasjonen vår og samle byggresultatet src / main / webapp / WEB-INF / view / react / build.

5. Konklusjon

I denne artikkelen har vi dekket hvordan du bygger en React-påloggingsapp og la den samhandle med en Spring Security-backend. En mer kompleks applikasjon vil innebære tilstandsovergang og ruting ved hjelp av React Router eller Redux, men det vil være utenfor omfanget av denne artikkelen.

Som alltid kan full implementering bli funnet på GitHub. For å kjøre det lokalt, kjør mvn brygge: løp i prosjektets rotmappe, så kan vi få tilgang til React login-siden på // lokal vert: 8080.


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