Registrácia - aktivujte nový účet e-mailom

Tento článok je súčasťou série: • Výukový program pre jarnú registráciu zabezpečenia

• Proces registrácie s jarnou bezpečnosťou

• Registrácia - Aktivácia nového účtu e-mailom (aktuálny článok) • Jarná bezpečnostná registrácia - Opätovné odoslanie overovacieho e-mailu

• Registrácia s Spring Security - kódovanie hesla

• Registračné API sa stáva RESTful

• Jarná bezpečnosť - obnovte svoje heslo

• Registrácia - sila hesla a pravidlá

• Aktualizácia hesla

1. Prehľad

Tento článok pokračuje ďalej Registrácia s jarným zabezpečením série s jednou z chýbajúcich častí procesu registrácie - overenie e-mailu používateľa na potvrdenie jeho účtu.

Mechanizmus potvrdenia registrácie núti používateľa reagovať na „Potvrďte registráciu”Zaslaný e-mail po úspešnej registrácii na overenie jeho e-mailovej adresy a aktivácia ich účtu. Používateľ to urobí kliknutím na jedinečný aktivačný odkaz, ktorý mu bude zaslaný e-mailom.

Podľa tejto logiky sa novo registrovaný používateľ nebude môcť prihlásiť do systému, kým sa tento proces nedokončí.

2. Overovací token

Ako kľúčový artefakt, prostredníctvom ktorého je používateľ overený, použijeme jednoduchý overovací token.

2.1. The VerificationToken Subjekt

The VerificationToken subjekt musí spĺňať nasledujúce kritériá:

  1. Musí odkazovať späť na Používateľ (prostredníctvom jednosmerného vzťahu)
  2. Vytvorí sa hneď po registrácii
  3. To bude vyprší do 24 hodín po jeho vytvorení
  4. jedinečný, náhodne vygenerovaný hodnotu

Požiadavky 2 a 3 sú súčasťou logiky registrácie. Ďalšie dva sú implementované jednoduchým spôsobom VerificationToken entita ako v príklade 2.1 .:

Príklad 2.1.

@Entity verejná trieda VerificationToken {private static final int EXPIRATION = 60 * 24; @Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; súkromný reťazcový token; @OneToOne (targetEntity = User.class, fetch = FetchType.EAGER) @JoinColumn (nullable = false, name = "user_id") súkromný používateľ; súkromné ​​Dátum vypršania platnosti; private Date CalcExpiryDate (int expiryTimeInMinutes) {Calendar cal = Calendar.getInstance (); cal.setTime (nová časová značka (cal.getTime (). getTime ())); cal.add (Calendar.MINUTE, expiryTimeInMinutes); vrátiť nový dátum (cal.getTime (). getTime ()); } // štandardné konštruktory, getre a setre}

Všimnite si nullable = false na Užívateľovi, aby zabezpečil integritu a konzistenciu údajov v VerificationToken <->Používateľ združenie.

2.2. Pridajte znak povolené Pole do Používateľ

Spočiatku, keď Používateľ je zaregistrovaný, toto povolené pole bude nastavené na nepravdivé. Ak bude proces overenia účtu úspešný, stane sa pravda.

Začnime tým, že pridáme pole k nášmu Používateľ subjekt:

public class User {... @Column (name = "enabled") private boolean enabled; public User () {super (); this.enabled = false; } ...}

Všimnite si, ako sme tiež nastavili predvolenú hodnotu tohto poľa na nepravdivé.

3. Počas registrácie účtu

Pridajme do prípadu použitia registrácie používateľa ďalšie dve časti obchodnej logiky:

  1. Vytvorte VerificationToken pre Používateľa a trvať na tom
  2. Poslať e-mailovú správu na potvrdenie účtu - ktorá obsahuje potvrdzovací odkaz s VerificationToken hodnotu

3.1. Použite jarnú udalosť na vytvorenie tokenu a odoslanie verifikačného e-mailu

Tieto dve ďalšie časti logiky by nemal vykonávať priamo kontrolór, pretože ide o vedľajšie úlohy typu „collateral“.

Kontrolór zverejní jar ApplicationEvent na vykonanie týchto úloh. Je to tak jednoduché ako vpichnutie injekcie ApplicationEventPublisher a potom ho použiť na zverejnenie dokončenia registrácie.

Príklad 3.1. ukazuje túto jednoduchú logiku:

Príklad 3.1.

@Autowired ApplicationEventPublisher eventPublisher @PostMapping ("/ user / registration") public ModelAndView registerUserAccount (@ModelAttribute ("user") @Valid UserDto userDto, požiadavka HttpServletRequest, chyby chýb) {try {User registered = userService.registerNewUserAccount Reťazec appUrl = request.getContextPath (); eventPublisher.publishEvent (nový OnRegistrationCompleteEvent (registrovaný, request.getLocale (), appUrl)); } catch (UserAlreadyExistException uaeEx) {ModelAndView mav = nový ModelAndView ("registrácia", "užívateľ", userDto); mav.addObject ("správa", "Účet pre dané používateľské meno / e-mail už existuje."); návrat mav; } catch (RuntimeException ex) {return new ModelAndView ("emailError", "user", userDto); } vrátiť nový ModelAndView ("successRegister", "user", userDto); }

Jedna ďalšia vec, ktorú si musíte všimnúť, je Skús chytiť blok okolo zverejnenia udalosti. Táto časť kódu zobrazí chybovú stránku vždy, keď dôjde k výnimke v logike vykonanej po zverejnení udalosti, ktorou je v tomto prípade odoslanie e-mailu.

3.2. Udalosť a poslucháč

Pozrime sa teraz na skutočnú implementáciu tohto nového OnRegistrationCompleteEvent ktorý vysiela náš radič, ako aj poslucháč, ktorý to bude vybavovať:

Príklad 3.2.1. - OnRegistrationCompleteEvent

verejná trieda OnRegistrationCompleteEvent rozširuje ApplicationEvent {private String appUrl; súkromné ​​miestne nastavenie; súkromný užívateľ; public OnRegistrationCompleteEvent (používateľ používateľa, miestne nastavenie miestneho prostredia, reťazec appUrl) {super (používateľ); this.user = užívateľ; this.locale = miestne nastavenie; this.appUrl = appUrl; } // štandardní zakladatelia a zakladatelia}

Príklad 3.2.2. Registračný zoznam Rukoväte OnRegistrationCompleteEvent

@ Komponentná verejná trieda RegistrationListener implementuje ApplicationListener {@Autowired súkromná služba IUserService; @Autowired súkromné ​​správy MessageSource; @Autowired private JavaMailSender mailSender; @Override public void onApplicationEvent (udalosť OnRegistrationCompleteEvent) {this.confirmRegistration (udalosť); } private void confirmRegistration (OnRegistrationCompleteEvent event) {User user = event.getUser (); Reťazcový token = UUID.randomUUID (). ToString (); service.createVerificationToken (používateľ, token); Reťazec recipientAddress = user.getEmail (); Predmet reťazca = "Potvrdenie registrácie"; Reťazec confirmationUrl = event.getAppUrl () + "/regitrationConfirm.html?token=" + token; Reťazec message = messages.getMessage ("message.regSucc", null, event.getLocale ()); SimpleMailMessage email = nový SimpleMailMessage (); email.setTo (recipientAddress); email.setSubject (predmet); email.setText (správa + "\ r \ n" + "// localhost: 8080" + confirmationUrl); mailSender.send (e-mail); }}

Tu je potvrdiťRegistrácia metóda dostane OnRegistrationCompleteEvent, extrahujte všetky potrebné Používateľ informácie z neho, vytvorte overovací token, uložte ho a potom ho pošlite ako parameter v poli „Potvrďte registráciu”Odkaz.

Ako už bolo spomenuté vyššie, akékoľvek javax.mail.AuthenticationFailedException vyhodený JavaMailSender vybaví kontrolór.

3.3. Spracovanie parametra overovacieho tokenu

Keď používateľ dostane správuPotvrďte registráciu”, Mali by na ňu kliknúť.

Akonáhle to urobia - kontrolór extrahuje hodnotu parametra tokenu vo výslednej požiadavke GET a použije ju na povolenie Používateľ.

Pozrime sa na tento proces v príklade 3.3.1 .:

Príklad 3.3.1. - RegistrationController Spracovanie potvrdenia o registrácii

@Autowired súkromná služba IUserService; @GetMapping ("/ regitrationConfirm") public String confirmRegistration (požiadavka WebRequest, model modelu, @RequestParam ("token") reťazec) {Locale locale = request.getLocale (); VerificationToken verificationToken = service.getVerificationToken (token); if (verificationToken == null) {String message = messages.getMessage ("auth.message.invalidToken", null, locale); model.addAttribute ("správa", správa); return "redirect: /badUser.html? lang =" + locale.getLanguage (); } Používateľ user = verificationToken.getUser (); Calendar cal = Calendar.getInstance (); if ((verificationToken.getExpiryDate (). getTime () - cal.getTime (). getTime ()) <= 0) {String messageValue = messages.getMessage ("auth.message.expired", null, locale) model.addAttribute ("správa", messageValue); return "redirect: /badUser.html? lang =" + locale.getLanguage (); } user.setEnabled (true); service.saveRegisteredUser (užívateľ); return "redirect: /login.html? lang =" + request.getLocale (). getLanguage (); }

Používateľ bude presmerovaný na chybovú stránku s príslušnou správou, ak:

  1. The VerificationToken neexistuje, z nejakého dôvodu resp
  2. The VerificationToken vypršal

Pozri príklad 3.3.2. zobraziť chybovú stránku.

Príklad 3.3.2. - badUser.html

Ako vidíme, teraz MyUserDetailsService nepoužíva povolené príznak používateľa - a teda umožní iba autentifikáciu povoleného používateľa.

Teraz pridáme znak AuthenticationFailureHandler prispôsobiť správy o výnimkách pochádzajúce z MyUserDetailsService. Náš CustomAuthenticationFailureHandler je uvedený v príklade 4.2.:

Príklad 4.2. - CustomAuthenticationFailureHandler:

@ Verejná trieda komponentu CustomAuthenticationFailureHandler rozširuje SimpleUrlAuthenticationFailureHandler {@Autowired súkromné ​​správy MessageSource; @Autowired private LocaleResolver localeResolver; @Override public void onAuthenticationFailure (požiadavka HttpServletRequest, odpoveď HttpServletResponse, výnimka AuthenticationException) hodí IOException, ServletException {setDefaultFailureUrl ("/ login.html? Error = true"); super.onAuthenticationFailure (požiadavka, odpoveď, výnimka); Locale locale = localeResolver.resolveLocale (požiadavka); Reťazec errorMessage = messages.getMessage ("message.badCredentials", null, miestne nastavenie); if (exception.getMessage (). equalsIgnoreCase ("Užívateľ je vypnutý")) {errorMessage = messages.getMessage ("auth.message.disabled", null, locale); } else if (exception.getMessage (). equalsIgnoreCase ("Platnosť používateľského účtu vypršala")) {errorMessage = messages.getMessage ("auth.message.expired", null, locale); } request.getSession (). setAttribute (WebAttributes.AUTHENTICATION_EXCEPTION, errorMessage); }}

Budeme musieť upraviť login.html zobraziť chybové správy.

Príklad 4.3. - Zobraziť chybové správy na login.html:

 chyba 

5. Prispôsobenie vrstvy perzistencie

Poďme teraz poskytnúť skutočnú implementáciu niektorých z týchto operácií zahŕňajúcich overovací token, ako aj používateľov.

Pokryjeme:

  1. Nový VerificationTokenRepository
  2. Nové metódy v IUserInterface a je potrebná jeho implementácia pre nové operácie CRUD

Príklady 5.1 - 5.3. ukážte nové rozhrania a implementáciu:

Príklad 5.1. - VerificationTokenRepository

verejné rozhranie VerificationTokenRepository rozširuje JpaRepository {VerificationToken findByToken (reťazcový token); VerificationToken findByUser (užívateľský užívateľ); }

Príklad 5.2. - IUserService Rozhranie

verejné rozhranie IUserService {User registerNewUserAccount (UserDto userDto) hodí UserAlreadyExistException; Používateľ getUser (String verificationToken); void saveRegisteredUser (užívateľský užívateľ); void createVerificationToken (užívateľ užívateľa, reťazec token); VerificationToken getVerificationToken (String VerificationToken); }

Príklad 5.3. The UserService

@Service @Transactional verejná trieda UserService implementuje IUserService {@Autowired súkromné ​​úložisko UserRepository; @Autowired private VerificationTokenRepository tokenRepository; @Override public User registerNewUserAccount (UserDto userDto) hodí UserAlreadyExistException {if (emailExist (userDto.getEmail ())) {hodiť novú UserAlreadyExistException ("Existuje účet s touto e-mailovou adresou:" + userDto.getEmail ()); } User user = new User (); user.setFirstName (userDto.getFirstName ()); user.setLastName (userDto.getLastName ()); user.setPassword (userDto.getPassword ()); user.setEmail (userDto.getEmail ()); user.setRole (new Role (Integer.valueOf (1), user)); return repository.save (užívateľ); } private boolean emailExist (String email) {return userRepository.findByEmail (email)! = null; } @Override public User getUser (String verificationToken) {User user = tokenRepository.findByToken (verificationToken) .getUser (); návratový užívateľ; } @Override public VerificationToken getVerificationToken (String VerificationToken) {return tokenRepository.findByToken (VerificationToken); } @Override public void saveRegisteredUser (užívateľský užívateľ) {repository.save (užívateľ); } @Override public void createVerificationToken (užívateľský užívateľ, token reťazca) {VerificationToken myToken = nový VerificationToken (token, užívateľ); tokenRepository.save (myToken); }}

6. Záver

V tomto článku sme rozšírili proces registrácie o e-mailový postup aktivácie účtu.

Logika aktivácie účtu vyžaduje zaslanie overovacieho tokenu používateľovi prostredníctvom e-mailu, aby ho mohol poslať späť správcovi na overenie jeho totožnosti.

Implementáciu tohto tutoriálu Registrácia s jarným zabezpečením nájdete v projekte GitHub - jedná sa o projekt založený na Eclipse, takže by malo byť ľahké ho importovať a spustiť tak, ako je.

Ďalšie » Jarná bezpečnostná registrácia - znova odoslať overovací e-mail « Predchádzajúci Proces registrácie s jarnou bezpečnosťou

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