Dvofaktorska autorizacija s proljetnom sigurnošću

1. Pregled

U ovom uputstvu implementirat ćemo funkciju dvofaktorske provjere autentičnosti s soft tokenom i Spring Spring

Dodati ćemo novu funkcionalnost u postojeći, jednostavan tijek prijave i upotrijebiti aplikaciju Google Authenticator za generiranje tokena.

Jednostavno rečeno, dvofaktorska autentifikacija postupak je provjere koji slijedi dobro poznati princip "nešto što korisnik zna i nešto što korisnik ima".

Tako korisnici tijekom autentifikacije pružaju dodatni „token za provjeru“ - jednokratni kod za provjeru lozinke zasnovan na algoritmu TOTP za jednokratnu lozinku na temelju vremena.

2. Konfiguracija Maven

Prvo, da bismo koristili Google Authenticator u našoj aplikaciji, moramo:

  • Generiraj tajni ključ
  • Dajte tajni ključ korisniku putem QR-koda
  • Potvrdite token koji je korisnik unio pomoću ovog tajnog ključa.

Upotrijebit ćemo jednostavnu biblioteku na poslužitelju za generiranje / provjeru jednokratne lozinke dodavanjem sljedeće ovisnosti u našu pom.xml:

 org.jboss.aerogear aerogear-otp-java 1.0.0 

3. Korisnički entitet

Dalje, izmijenit ćemo svoj korisnički entitet da sadrži dodatne informacije - kako slijedi:

Korisnik javne klase @Entity {... private boolean isUsing2FA; privatna tajna niza; javni korisnik () {super (); this.secret = Base32.random (); ...}}

Imajte na umu da:

  • Spremamo slučajni tajni kod za svakog korisnika koji će se kasnije koristiti u stvaranju kontrolnog koda
  • Naša potvrda u 2 koraka nije obavezna

4. Dodatni parametar za prijavu

Prvo ćemo morati prilagoditi svoju sigurnosnu konfiguraciju kako bi prihvatili dodatni parametar - token za provjeru. To možemo postići koristeći običaj AuthenticationDetailsSource:

Ovdje je naš CustomWebAuthenticationDetailsSource:

@Component javna klasa CustomWebAuthenticationDetailsSource implementira AuthenticationDetailsSource {@Override public WebAuthenticationDetails buildDetails (HttpServletRequest context) {return new CustomWebAuthenticationDetails (context); }}

i ovdje je CustomWebAuthenticationDetails:

javna klasa CustomWebAuthenticationDetails proširuje WebAuthenticationDetails {private String verifyCode; javni CustomWebAuthenticationDetails (zahtjev HttpServletRequest) {super (zahtjev); verifyCode = request.getParameter ("kod"); } javni String getVerificationCode () {return verifyCode; }}

I naša sigurnosna konfiguracija:

@Configuration @EnableWebSecurity javna klasa LssSecurityConfig proširuje WebSecurityConfigurerAdapter {@Autowired private CustomWebAuthenticationDetailsSource authenticationDetailsSource; @Override zaštićena void konfiguracija (HttpSecurity http) baca iznimku {http.formLogin () .authenticationDetailsSource (authenticationDetailsSource) ...}}

I na kraju dodajte dodatni parametar u naš obrazac za prijavu:

 Verifikacijski kôd Google Autentifikatora 

Napomena: Moramo postaviti svoj običaj AuthenticationDetailsSource u našoj sigurnosnoj konfiguraciji.

5. Prilagođeni davatelj autentičnosti

Dalje, trebat će nam običaj AutentificationProvider za obradu validacije dodatnih parametara:

javna klasa CustomAuthenticationProvider proširuje DaoAuthenticationProvider {@Autowired private UserRepository userRepository; @Override public Authentication authentication (Authentication auth) baca AuthenticationException {String verifyCode = ((CustomWebAuthenticationDetails) auth.getDetails ()) .getVerificationCode (); Korisnik korisnik = userRepository.findByEmail (auth.getName ()); if ((user == null)) {throw new BadCredentialsException ("Nevažeće korisničko ime ili lozinka"); } if (user.isUsing2FA ()) {Totp totp = novi Totp (user.getSecret ()); if (! isValidLong (verifyCode) ||! totp.verify (verifyCode)) {throw new BadCredentialsException ("Nevažeći kod verfikacije"); }} Rezultat autentifikacije = super.authenticate (auth); vratiti novo UsernamePasswordAuthenticationToken (user, result.getCredentials (), result.getAuthorities ()); } private boolean isValidLong (String code) {try {Long.parseLong (code); } catch (NumberFormatException e) {return false; } return true; } @Override javna logička podrška (provjera autentičnosti klase) {return authentication.equals (UsernamePasswordAuthenticationToken.class); }}

Imajte na umu da smo nakon što smo provjerili jednokratni kod za potvrdu lozinke jednostavno prenijeli provjeru autentičnosti nizvodno.

Ovdje je naš grah davatelja autentičnosti

@Bean public DaoAuthenticationProvider authProvider () {CustomAuthenticationProvider authProvider = novi CustomAuthenticationProvider (); authProvider.setUserDetailsService (userDetailsService); authProvider.setPasswordEncoder (encoder ()); vratiti authProvider; }

6. Postupak registracije

Sada, da bi korisnici mogli koristiti aplikaciju za generiranje tokena, morat će pravilno postaviti stvari kada se registriraju.

Dakle, morat ćemo napraviti nekoliko jednostavnih izmjena u postupku registracije - kako bismo korisnicima koji su odlučili koristiti potvrdu u dva koraka omogućili da skenirajte QR-kod koji im je potreban da se kasnije prijave.

Prvo, u obrazac za registraciju dodajemo ovaj jednostavan unos:

Upotrijebite potvrdu u dva koraka 

Zatim, u našem RegistrationController - preusmjeravamo korisnike na temelju njihovih izbora nakon potvrde registracije:

@GetMapping ("/ registrationConfirm") javni niz confirmRegistration (@RequestParam ("token") Token niza, ...) {Rezultat niza = userService.validateVerificationToken (token); if (result.equals ("valid")) {Korisnik korisnik = userService.getUser (token); if (user.isUsing2FA ()) {model.addAttribute ("qr", userService.generateQRUrl (korisnik)); vrati "preusmjeravanje: /qrcode.html? lang =" + locale.getLanguage (); } model.addAttribute ("message", messages.getMessage ("message.accountVerified", null, locale)); vrati "preusmjeravanje: / prijava? lang =" + locale.getLanguage (); } ...}

I ovdje je naša metoda generirajQRUrl ():

javni statički niz QR_PREFIX = "//chart.googleapis.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl="; @Override javni niz generirajQRUrl (korisnik korisnika) {return QR_PREFIX + URLEncoder.encode (String.format ("otpauth: // totp /% s:% s? Secret =% s & issuer =% s", APP_NAME, user.getEmail () , user.getSecret (), APP_NAME), "UTF-8"); }

I ovdje je naš qrcode.html:

Skenirajte ovaj crtični kôd pomoću aplikacije Google Authenticator na telefonu da biste ga kasnije koristili za prijavu

Idite na stranicu za prijavu

Imajte na umu da:

  • generirajQRUrl () metoda koristi se za generiranje URL-a QR-koda
  • Ovaj QR-kod skenirat će korisnici mobilnih telefona pomoću aplikacije Google Authenticator
  • Aplikacija će generirati 6-znamenkasti kôd koji vrijedi samo 30 sekundi, a to je željeni kontrolni kôd
  • Ovaj kontrolni kôd bit će provjeren tijekom prijave koristeći naš običaj AutentificationProvider

7. Omogućite potvrdu u dva koraka

Dalje, pobrinut ćemo se da korisnici mogu u bilo kojem trenutku promijeniti svoje postavke prijave - kako slijedi:

@PostMapping ("/ user / update / 2fa") javni GenericResponse modifyUser2FA (@RequestParam ("use2FA") boolean use2FA) baca UnsupportedEncodingException {User user = userService.updateUser2FA (use2FA); if (use2FA) {return new GenericResponse (userService.generateQRUrl (user)); } return null; }

I ovdje je updateUser2FA ():

@Override public User updateUser2FA (boolean use2FA) {Authentication curAuth = SecurityContextHolder.getContext (). GetAuthentication (); Korisnik currentUser = (Korisnik) curAuth.getPrincipal (); currentUser.setUsing2FA (use2FA); currentUser = repozitorij.save (currentUser); Autentifikacija auth = new UsernamePasswordAuthenticationToken (currentUser, currentUser.getPassword (), curAuth.getAuthorities ()); SecurityContextHolder.getContext (). SetAuthentication (auth); return currentUser; }

I evo prednjeg dijela:

 Koristite dvostepenu autentifikaciju Onemogući 2FA Ne koristite dvofaznu autentifikaciju Omogući 2FA

Skenirajte ovaj crtični kôd pomoću aplikacije Google Authenticator na telefonu

funkcija enable2FA () {set2FA (true); } funkcija disable2FA () {set2FA (false); } funkcija set2FA (use2FA) {$ .post ("/ user / update / 2fa", {use2FA: use2FA}, funkcija (podaci) {if (use2FA) {$ ("# qr"). append (''). show ();} else {window.location.reload ();}}); }

8. Zaključak

U ovom smo brzom uputstvu ilustrirali kako izvršiti dvofaktorsku implementaciju provjere autentičnosti pomoću soft tokena s Spring Security.

Cjeloviti izvorni kod možete pronaći - kao i uvijek do sada - na GitHubu.


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