Két faktoros hitelesítés a tavaszi biztonsággal

1. Áttekintés

Ebben az oktatóanyagban kétfaktoros hitelesítési funkciót fogunk megvalósítani egy Soft Token és Spring Security segítségével.

Hozzá fogjuk adni az új funkciót egy meglévő, egyszerű bejelentkezési folyamathoz, és a Google Authenticator alkalmazást használjuk a tokenek előállításához.

Egyszerűen fogalmazva, a kétfaktoros hitelesítés egy olyan ellenőrzési folyamat, amely a „valamit, amit a felhasználó tud, és amit a felhasználónak” jól ismert elvét követi.

Így a felhasználók egy további „ellenőrző tokent” biztosítanak a hitelesítés során - egyszeri jelszó-ellenőrző kódot, amely az Időalapú egyszeri jelszó TOTP algoritmuson alapul.

2. Maven konfiguráció

Először is, a Google Authenticator alkalmazásunkban való használatához:

  • Titkos kulcs létrehozása
  • Adjon meg titkos kulcsot a felhasználó számára QR-kódon keresztül
  • Ellenőrizze a felhasználó által megadott titkot ezzel a titkos kulccsal.

Egyszerű kiszolgálóoldali könyvtárat fogunk használni az egyszeri jelszó előállításához / ellenőrzéséhez a következő függőség hozzáadásával pom.xml:

 org.jboss.aerogear aerogear-otp-java 1.0.0 

3. Felhasználói entitás

Ezután módosítjuk felhasználói entitásunkat további információk tárolására - az alábbiak szerint:

@Entity public class Felhasználó {... privát logikai isUsing2FA; privát String titok; public User () {super (); this.secret = Base32.random (); ...}}

Vegye figyelembe, hogy:

  • Mentünk egy véletlenszerű titkos kódot minden felhasználó számára, amelyet később használhatunk az ellenőrző kód létrehozásában
  • A kétlépcsős azonosítás nem kötelező

4. Extra bejelentkezési paraméter

Először módosítanunk kell a biztonsági konfigurációnkat, hogy elfogadjuk az extra paraméter - ellenőrző tokent. Megvalósíthatjuk ezt egyedi használatával AuthenticationDetailsSource:

Itt van a miénk CustomWebAuthenticationDetailsSource:

@Component public class CustomWebAuthenticationDetailsSource implementates AuthenticationDetailsSource {@Orride public WebAuthenticationDetails buildDetails (HttpServletRequest context) {return new CustomWebAuthenticationDetails (context); }}

és itt van CustomWebAuthenticationDetails:

public class CustomWebAuthenticationDetails kiterjeszti a WebAuthenticationDetails {private String verificationCode; public CustomWebAuthenticationDetails (HttpServletRequest kérés) {szuper (kérés); VerificationCode = request.getParameter ("kód"); } public String getVerificationCode () {return authentCode; }}

És a biztonsági konfigurációnk:

@Configuration @EnableWebSecurity LssSecurityConfig nyilvános osztály kiterjeszti a WebSecurityConfigurerAdapter {@Autowired private CustomWebAuthenticationDetailsSource authenticationDetailsSource; A @Orride védett void konfiguráció (HttpSecurity http) a {http.formLogin () .authenticationDetailsSource (authenticationDetailsSource) ...}} kivételt dobja

Végül adja hozzá az extra paramétert a bejelentkezési űrlapunkhoz:

 Google Authenticator ellenőrző kód 

Megjegyzés: Be kell állítanunk a szokásainkat AuthenticationDetailsSource biztonsági konfigurációnkban.

5. Egyéni hitelesítés-szolgáltató

Ezután szükségünk lesz egy szokásra AuthenticationProvider az extra paraméter-hitelesítés kezeléséhez:

public class CustomAuthenticationProvider kiterjeszti a DaoAuthenticationProvider {@Autowired private UserRepository userRepository; @ A nyilvános hitelesítési hitelesítés felülbírálása (hitelesítési hitelesítés) dobja az AuthenticationException {karakterlánc-ellenőrző kód = (((CustomWebAuthenticationDetails) hitelesítési adatok) ()) .getVerificationCode (); Felhasználói felhasználó = userRepository.findByEmail (auth.getName ()); if ((user == null)) {dobjon új BadCredentialsException-t ("Érvénytelen felhasználónév vagy jelszó"); } if (user.isUsing2FA ()) {Totp totp = new Totp (user.getSecret ()); if (! isValidLong (VerificationCode) ||! totp.verify (VerificationCode)) {dobjon új BadCredentialsException-t ("Érvénytelen ellenőrző kód"); }} Hitelesítési eredmény = szuper.hitelesítés (hitelesítés); return new UsernamePasswordAuthenticationToken (felhasználó, eredmény.getCredentials (), eredmény.getAuthorities ()); } privát logikai isValidLong (karakterlánc kód) {próbálkozzon {Long.parseLong (kód); } catch (NumberFormatException e) {return false; } return true; } @Orride nyilvános logikai támogatások (osztályhitelesítés) {return authentication.equals (UsernamePasswordAuthenticationToken.class); }}

Ne feledje, hogy - miután ellenőriztük az egyszeri jelszó-ellenőrző kódot, egyszerűen továbbadtuk a hitelesítést a későbbiekben.

Itt van a hitelesítés-szolgáltatónk bab

@Bean public DaoAuthenticationProvider authProvider () {CustomAuthenticationProvider authProvider = new CustomAuthenticationProvider (); authProvider.setUserDetailsService (userDetailsService); authProvider.setPasswordEncoder (kódoló ()); return authProvider; }

6. Regisztráció folyamata

Most, hogy a felhasználók az alkalmazást használhassák a tokenek előállításához, a regisztrációkor megfelelően be kell állítaniuk a dolgokat.

Ezért néhány egyszerű módosítást kell végrehajtanunk a regisztrációs folyamatban - hogy a kétlépcsős azonosítást választó felhasználók beolvassa a későbbi bejelentkezéshez szükséges QR-kódot.

Először ezt az egyszerű bevitelt adjuk a regisztrációs űrlapunkhoz:

Használjon kétlépcsős azonosítást 

Aztán a mi RegistrationController - a felhasználókat választásuk alapján átirányítjuk a regisztráció megerősítése után:

@GetMapping ("/ registrationConfirm") public String confirmRegistration (@RequestParam ("token") String token, ...) {String result = userService.validateVerificationToken (token); if (result.equals ("érvényes")) {User user = userService.getUser (token); if (user.isUsing2FA ()) {model.addAttribute ("qr", userService.generateQRUrl (felhasználó)); return "redirect: /qrcode.html? lang =" + locale.getLanguage (); } model.addAttribute ("message", messages.getMessage ("message.accountVerified", null, locale)); return "redirect: / login? lang =" + locale.getLanguage (); } ...}

És itt van a módszerünk generálniQRUrl ():

nyilvános statikus karakterlánc QR_PREFIX = "//chart.googleapis.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl="; @ Nyissa meg a nyilvános karakterláncot , user.getSecret (), APP_NAME), "UTF-8"); }

És itt van a miénk qrcode.html:

Olvassa be ezt a vonalkódot a telefonján található Google Authenticator alkalmazással, hogy később bejelentkezéskor használhassa

Lépjen a bejelentkezési oldalra

Vegye figyelembe, hogy:

  • generálQRUrl () metódust használnak a QR-kód URL létrehozására
  • Ezt a QR-kódot a felhasználók mobiltelefonjai beolvassák a Google Authenticator alkalmazás segítségével
  • Az alkalmazás létrehoz egy 6 jegyű kódot, amely csak 30 másodpercig érvényes, ami a kívánt ellenőrző kód
  • Ezt az ellenőrző kódot a szokásunkkal történő bejelentkezés során ellenőrizzük AuthenticationProvider

7. Engedélyezze a kétlépcsős azonosítást

Ezután megbizonyosodunk arról, hogy a felhasználók bármikor megváltoztathatják bejelentkezési beállításait - az alábbiak szerint:

@PostMapping ("/ user / update / 2fa") public GenericResponse modifyUser2FA (@RequestParam ("use2FA") logikai felhasználás2FA) dobja az UnsupportedEncodingException {User user = userService.updateUser2FA (use2FA); if (use2FA) {return new GenericResponse (userService.generateQRUrl (felhasználó)); } return null; }

És itt van updateUser2FA ():

@ Nyilvános felhasználói frissítés felülbírálásaUser2FA (logikai használat2FA) {Authentication curAuth = SecurityContextHolder.getContext (). GetAuthentication (); Felhasználó currentUser = (Felhasználó) curAuth.getPrincipal (); currentUser.setUsing2FA (use2FA); currentUser = adattár.save (currentUser); Hitelesítés auth = new UsernamePasswordAuthenticationToken (currentUser, currentUser.getPassword (), curAuth.getAuthorities ()); SecurityContextHolder.getContext (). SetAuthentication (auth); return currentUser; }

És itt van a kezelőfelület:

 Kétlépcsős hitelesítést használ A 2FA letiltása Nem a kétlépcsős hitelesítést használja a 2FA engedélyezését

Olvassa be ezt a vonalkódot a telefonján található Google Authenticator alkalmazással

function enable2FA () {set2FA (true); } function disable2FA () {set2FA (hamis); } function set2FA (use2FA) {$ .post ("/ user / update / 2fa", {use2FA: use2FA}, function (data) {if (use2FA) {$ ("# qr"). addend (''). show ();} else {window.location.reload ();}}); }

8. Következtetés

Ebben a gyors bemutatóban bemutattuk, hogyan lehet kétfaktoros hitelesítést végrehajtani egy Soft Token és Spring Security használatával.

A teljes forráskód - mint mindig - a GitHubon található.