Two Factor Auth med vårsikkerhet

1. Oversikt

I denne opplæringen skal vi implementere tofaktorautentiseringsfunksjonalitet med en myk token og vårsikkerhet.

Vi skal legge til den nye funksjonaliteten i en eksisterende, enkel påloggingsflyt og bruke Google Authenticator-appen til å generere tokens.

Enkelt sagt er tofaktorautentisering en bekreftelsesprosess som følger det velkjente prinsippet om "noe brukeren vet og noe brukeren har".

Og så gir brukerne et ekstra "bekreftelsestoken" under autentisering - en engangskode for bekreftelse av passord basert på tidsbasert engangspassord TOTP-algoritme.

2. Maven-konfigurasjon

Først, for å kunne bruke Google Authenticator i appen vår, må vi:

  • Generer hemmelig nøkkel
  • Gi hemmelig nøkkel til brukeren via QR-kode
  • Bekreft token som er angitt av brukeren ved hjelp av denne hemmelige nøkkelen.

Vi vil bruke et enkelt serverbibliotek for å generere / verifisere engangspassord ved å legge til følgende avhengighet til vårt pom.xml:

 org.jboss.aerogear aerogear-otp-java 1.0.0 

3. Brukerenhet

Deretter vil vi endre brukerenheten vår for å ha ekstra informasjon - som følger:

@Entity public class User {... private boolean isUsing2FA; privat streng hemmelighet; offentlig bruker () {super (); this.secret = Base32.random (); ...}}

Noter det:

  • Vi lagrer en tilfeldig hemmelig kode for hver bruker som skal brukes senere ved generering av bekreftelseskode
  • Vår 2-trinns bekreftelse er valgfri

4. Ekstra innloggingsparameter

Først må vi justere sikkerhetskonfigurasjonen for å godta ekstra parameter - bekreftelsestoken. Vi kan oppnå det ved å bruke tilpasset AuthenticationDetailsSource:

Her er vår CustomWebAuthenticationDetailsSource:

@Komponent offentlig klasse CustomWebAuthenticationDetailsSource implementerer AuthenticationDetailsSource {@Override public WebAuthenticationDetails buildDetails (HttpServletRequest context) {return new CustomWebAuthenticationDetails (context); }}

og her er CustomWebAuthenticationDetails:

offentlig klasse CustomWebAuthenticationDetails utvider WebAuthenticationDetails {private String verificationCode; offentlige CustomWebAuthenticationDetails (HttpServletRequest forespørsel) {super (forespørsel); verificationCode = request.getParameter ("kode"); } public String getVerificationCode () {return verificationCode; }}

Og vår sikkerhetskonfigurasjon:

@Configuration @EnableWebSecurity offentlig klasse LssSecurityConfig utvider WebSecurityConfigurerAdapter {@Autowired private CustomWebAuthenticationDetailsSource authenticationDetailsSource; @ Override beskyttet ugyldig konfigurasjon (HttpSecurity http) kaster unntak {http.formLogin () .authenticationDetailsSource (authenticationDetailsSource) ...}}

Og til slutt legger du til den ekstra parameteren i påloggingsskjemaet vårt:

 Bekreftelseskode for Google Authenticator 

Merk: Vi må angi vår tilpassede AuthenticationDetailsSource i vår sikkerhetskonfigurasjon.

5. Tilpasset godkjenningsleverandør

Deretter trenger vi en tilpasset AuthenticationProvider for å håndtere ekstra parametervalidering:

offentlig klasse CustomAuthenticationProvider utvider DaoAuthenticationProvider {@Autowired private UserRepository userRepository; @Override public Authentication authenticate (Authentication auth) kaster AuthenticationException {String verificationCode = ((CustomWebAuthenticationDetails) auth.getDetails ()) .getVerificationCode (); Brukerbruker = userRepository.findByEmail (auth.getName ()); if ((user == null)) {throw new BadCredentialsException ("Ugyldig brukernavn eller passord"); } hvis (user.isUsing2FA ()) {Totp totp = ny Totp (user.getSecret ()); if (! isValidLong (verificationCode) ||! totp.verify (verificationCode)) {throw new BadCredentialsException ("Ugyldig verfication code"); }} Autentiseringsresultat = super.authenticate (auth); returner nytt UsernamePasswordAuthenticationToken (bruker, result.getCredentials (), result.getAuthorities ()); } privat boolsk isValidLong (strengkode) {prøv {Long.parseLong (kode); } fange (NumberFormatException e) {return false; } returner sant; } @Override public boolean supports (Class authentication) {return authentication.equals (UsernamePasswordAuthenticationToken.class); }}

Merk at - etter at vi har bekreftet bekreftelseskoden for engangspassord, delegerte vi bare autentisering nedstrøms.

Her er vår Authentication Provider-bønne

@Bean offentlig DaoAuthenticationProvider authProvider () {CustomAuthenticationProvider authProvider = ny CustomAuthenticationProvider (); authProvider.setUserDetailsService (userDetailsService); authProvider.setPasswordEncoder (koder ()); return authProvider; }

6. Registreringsprosess

Nå, for at brukere skal kunne bruke applikasjonen til å generere tokens, må de sette opp ting riktig når de registrerer seg.

Og så må vi gjøre noen få enkle endringer i registreringsprosessen - for å la brukere som har valgt å bruke totrinnsbekreftelse, skann QR-koden de trenger for å logge inn senere.

Først legger vi til denne enkle innspillingen i registreringsskjemaet:

Bruk totrinnsbekreftelse 

Så, i vår RegistrationController - vi omdirigerer brukere basert på deres valg etter bekreftelse av registreringen:

@GetMapping ("/ registrationConfirm") offentlig Strengbekreftelsesregistrering (@RequestParam ("token") Strengetoken, ...) {Stringresultat = userService.validateVerificationToken (token); hvis (result.equals ("valid")) {User user = userService.getUser (token); hvis (user.isUsing2FA ()) {model.addAttribute ("qr", userService.generateQRUrl (bruker)); return "redirect: /qrcode.html? lang =" + locale.getLanguage (); } model.addAttribute ("melding", messages.getMessage ("melding.kontoVerifisert", null, sted)); returner "redirect: / login? lang =" + locale.getLanguage (); } ...}

Og her er metoden vår generereQRUrl ():

offentlig statisk streng QR_PREFIX = "//chart.googleapis.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl="; @ Overstyr offentlig streng generereQRUrl (brukerbruker) {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"); }

Og her er vår qrcode.html:

Skann denne strekkoden ved hjelp av Google Authenticator-appen på telefonen din for å bruke den senere ved pålogging

Gå til påloggingssiden

Noter det:

  • generereQRUrl () metoden brukes til å generere QR-kode URL
  • Denne QR-koden vil bli skannet av brukerens mobiltelefoner ved hjelp av Google Authenticator-appen
  • Appen genererer en sekssifret kode som er gyldig i bare 30 sekunder, som er ønsket bekreftelseskode
  • Denne bekreftelseskoden vil bli bekreftet mens du logger på med vår tilpassede AuthenticationProvider

7. Aktiver totrinnsbekreftelse

Deretter vil vi sørge for at brukere når som helst kan endre innloggingsinnstillingene sine - som følger:

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

Og her er updateUser2FA ():

@ Override offentlig brukeroppdatering User2FA (boolsk use2FA) {Authentication curAuth = SecurityContextHolder.getContext (). GetAuthentication (); User currentUser = (User) curAuth.getPrincipal (); currentUser.setUsing2FA (use2FA); currentUser = repository.save (currentUser); Authentication auth = new UsernamePasswordAuthenticationToken (currentUser, currentUser.getPassword (), curAuth.getAuthorities ()); SecurityContextHolder.getContext (). SetAuthentication (auth); returstrøm Bruker; }

Og her er frontend:

 Du bruker totrinns autentisering Deaktiver 2FA Du bruker ikke totrinns autentisering Aktiver 2FA

Skann denne strekkoden med Google Authenticator-appen på telefonen din

function enable2FA () {set2FA (true); } funksjon disable2FA () {set2FA (false); } funksjon set2FA (use2FA) {$ .post ("/ user / update / 2fa", {use2FA: use2FA}, function (data) {if (use2FA) {$ ("# qr"). append (''). vis ();} annet {window.location.reload ();}}); }

8. Konklusjon

I denne raske opplæringen illustrerte vi hvordan du utfører en tofaktorautentiseringsimplementering ved hjelp av en Soft Token med Spring Security.

Hele kildekoden finner du - som alltid - over på GitHub.


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