Regisztráció - Új fiók aktiválása e-mailben

Ez a cikk egy sorozat része: • Tavaszi biztonsági regisztráció bemutató

• A regisztráció folyamata tavaszi biztonsággal

• Regisztráció - Új fiók aktiválása e-mailben (aktuális cikk) • Tavaszi biztonsági regisztráció - Ellenőrző e-mail újraküldése

• Regisztráció a Spring Security-nél - Jelszó kódolás

• A Registration API RESTful lesz

• Tavaszi biztonság - állítsa vissza jelszavát

• Regisztráció - A jelszó erőssége és szabályai

• Jelszavának frissítése

1. Áttekintés

Ez a cikk folytatja a folyamatban lévő folyamatot Regisztráció a Spring Security-nél sorozat a regisztrációs folyamat egyik hiányzó részével - a felhasználó e-mailjének igazolása a fiók megerősítéséhez.

A regisztráció megerősítésének mechanizmusa arra kényszeríti a felhasználót, hogy válaszoljon aErősítse meg a regisztrációt”Sikeres regisztráció után küldött e-mailt az e-mail címének ellenőrzéséhez és a fiókjuk aktiválásához. A felhasználó ezt úgy teszi meg, hogy rákattint egy egyedi aktiválási linkre, amelyet e-mailben küldött neki.

Ezt a logikát követve egy újonnan regisztrált felhasználó nem fog bejelentkezni a rendszerbe, amíg ez a folyamat nem fejeződik be.

2. Ellenőrző token

Egy egyszerű ellenőrző tokent fogunk használni, mint kulcselemet, amelyen keresztül a felhasználót ellenőrizzük.

2.1. A VerificationToken Entitás

A VerificationToken a gazdálkodó egységnek meg kell felelnie a következő kritériumoknak:

  1. Vissza kell kapcsolódnia a Felhasználó (egyirányú reláción keresztül)
  2. A regisztráció után azonnal létrejön
  3. Fog 24 órán belül lejár létrejöttét követően
  4. Van egy egyedi, véletlenszerűen generált érték

A 2. és 3. követelmény a regisztrációs logika része. A másik kettő egyszerű módon valósul meg VerificationToken a 2.1. példában szereplő entitás:

2.1. Példa

@Entity public class VerificationToken {private static final int EXPIRATION = 60 * 24; @Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; privát String token; @OneToOne (targetEntity = User.class, fetch = FetchType.EAGER) @JoinColumn (nullable = false, name = "user_id") privát felhasználói felhasználó; privát Dátum lejárati dátum; privát dátum calcExpiryDate (int expiryTimeInMinutes) {Naptár cal = Calendar.getInstance (); cal.setTime (új időbélyeg (cal.getTime (). getTime ())); cal.add (Naptár.MINUTE, expiryTimeInMinutes); return new Date (cal.getTime (). getTime ()); } // szabványos kivitelezők, mérőeszközök és beállítók}

Vegye figyelembe a nullable = false a felhasználót, hogy biztosítsa az adatok integritását és következetességét a VerificationToken <->Felhasználó Egyesület.

2.2. Add hozzá a engedélyezve Field to Felhasználó

Kezdetben, amikor a Felhasználó be van jegyezve, ez engedélyezve mező értéke hamis. A számlaellenőrzési folyamat során - ha sikeres lesz - ez lesz igaz.

Kezdjük azzal, hogy hozzáadjuk a mezőt a sajátunkhoz Felhasználó entitás:

public class Felhasználó {... @Column (név = "engedélyezve") privát logikai érték engedélyezve; public User () {super (); ez.engedélyezve = hamis; } ...}

Vegye figyelembe, hogyan állítottuk be a mező alapértelmezett értékét is hamis.

3. A számla regisztrációja során

Adjunk hozzá két további üzleti logikát a felhasználói regisztráció használati esetéhez:

  1. Generálja a VerificationToken a Felhasználó számára, és tartsa fenn
  2. Küldje el az e-mailt a fiók megerősítéséhez - amely tartalmaz egy megerősítő linket a VerificationToken's érték

3.1. Tavaszi esemény használata a token létrehozásához és az ellenőrző e-mail küldéséhez

Ezt a két további logikai elemet a vezérlő nem hajthatja végre közvetlenül, mivel ezek „kiegészítő” háttérfeladatok.

Az adatkezelő tavaszt jelentet meg ApplicationEvent hogy kiváltsa e feladatok végrehajtását. Ez olyan egyszerű, mint az injekció beadása ApplicationEventPublisher majd felhasználja a regisztráció befejezésének közzétételére.

3.1. Példa ezt az egyszerű logikát mutatja:

3.1. Példa

@Autowired ApplicationEventPublisher eventPublisher @PostMapping ("/ user / registration") public ModelAndView registerUserAccount (@ModelAttribute ("user") @Valid UserDto userDto, HttpServletRequest request, Hibák hibái) {próbálkozzon {Felhasználó regisztrált = userServiceAregisterNewUser Karakterlánc appUrl = request.getContextPath (); eventPublisher.publishEvent (új OnRegistrationCompleteEvent (regisztrált, request.getLocale (), appUrl)); } catch (UserAlreadyExistException uaeEx) {ModelAndView mav = új ModelAndView ("regisztráció", "felhasználó", userDto); mav.addObject ("message", "Már létezik fiók az adott felhasználónévhez / e-mailhez."); return mav; } catch (RuntimeException ex) {return new ModelAndView ("emailError", "user", userDto); } return new ModelAndView ("successRegister", "user", userDto); }

Egy további dolog, amit észre kell venni, az a próbáld elkapni blokk körül az esemény közzététele. Ez a kóddarab egy hibaoldalt jelenít meg, amikor az esemény közzététele után végrehajtott logikában van kivétel, amely ebben az esetben az e-mail elküldése.

3.2. Az esemény és a hallgató

Most nézzük meg ennek az újnak a tényleges megvalósítását OnRegistrationCompleteEvent hogy kontrollerünk kiküldi, valamint a hallgatót, aki kezeli:

3.2.1. Példa - A OnRegistrationCompleteEvent

public class OnRegistrationCompleteEvent kiterjeszti az ApplicationEvent {private String appUrl; privát Locale locale; privát Felhasználó felhasználó; public OnRegistrationCompleteEvent (felhasználói felhasználó, területi beállítás, String appUrl) {szuper (felhasználó); this.user = felhasználó; this.locale = területi beállítás; this.appUrl = appUrl; } // szokásos mérőeszközök és beállítók}

3.2.2. Példa A RegistrationListener Kezeli a OnRegistrationCompleteEvent

A @Component public class RegistrationListener végrehajtja az ApplicationListener {@Autowired private IUserService szolgáltatást; @Autowired privát MessageSource üzenetek; @Autowired privát JavaMailSender mailSender; @Orride public void onApplicationEvent (OnRegistrationCompleteEvent event) {this.confirmRegistration (event); } private void confirmRegistration (OnRegistrationCompleteEvent esemény) {Felhasználó = esemény.getUser (); String token = UUID.randomUUID (). ToString (); service.createVerificationToken (felhasználó, token); Karakterlánc recipientAddress = user.getEmail (); Karaktersorozat = "Regisztráció megerősítése"; Karakterlánc-megerősítésUrl = event.getAppUrl () + "/regitrationConfirm.html?token=" + token; Karakterlánc üzenet = messages.getMessage ("message.regSucc", null, event.getLocale ()); SimpleMailMessage email = új SimpleMailMessage (); email.setTo (recipientAddress); email.setSubject (tárgy); email.setText (message + "\ r \ n" + "// localhost: 8080" + confirmationUrl); mailSender.send (email); }}

Itt a confirmRegistration módszer megkapja a OnRegistrationCompleteEvent, kivonja az összes szükségeset Felhasználó információkat hozzon létre belőle, hozza létre az ellenőrző tokent, tartsa fenn, majd küldje el paraméterként a „Erősítse meg a regisztrációt”Link.

Mint fentebb említettük, bármelyik javax.mail.AuthenticationFailedException eldobta JavaMailSender a vezérlő kezeli.

3.3. Az ellenőrző token paraméter feldolgozása

Amikor a felhasználó megkapja aErősítse meg a regisztrációt”Linkre kell kattintaniuk.

Ha megteszik - a vezérlő kibontja a token paraméter értékét az eredményül kapott GET kérésben, és fel fogja használni a Felhasználó.

Lássuk ezt a folyamatot a 3.3.1 példában:

3.3.1. Példa - RegistrationController A regisztráció megerősítésének feldolgozása

@Autowired privát IUserService szolgáltatás; @GetMapping ("/ regitrationConfirm") public String confirmRegistration (WebRequest kérés, modellmodell, @RequestParam ("token") karakterlánc) {Locale locale = request.getLocale (); VerificationToken VerificationToken = service.getVerificationToken (token); if (VerificationToken == null) {Karakterlánc üzenet = messages.getMessage ("auth.message.invalidToken", null, területi beállítás); model.addAttribute ("üzenet", üzenet); return "redirect: /badUser.html? lang =" + locale.getLanguage (); } Felhasználó felhasználó = confirmationToken.getUser (); Naptár cal = Naptár.getInstance (); IF ("üzenet", messageValue); return "redirect: /badUser.html? lang =" + locale.getLanguage (); } user.setEnabled (true); service.saveRegisteredUser (felhasználó); return "redirect: /login.html? lang =" + request.getLocale (). getLanguage (); }

A felhasználót egy hibaoldalra irányítjuk a megfelelő üzenettel, ha:

  1. A VerificationToken nem létezik, valamilyen okból ill
  2. A VerificationToken lejárt

Lásd a 3.3.2. Példát. a hibaoldal megtekintéséhez.

3.3.2. Példa - A badUser.html

Mint láthatjuk, most MyUserDetailsService nem használja a engedélyezve a felhasználó jelzője - és így csak a felhasználó hitelesítését teszi lehetővé.

Most hozzáadunk egy AuthenticationFailureHandler testreszabhatja az innen érkező kivételüzeneteket MyUserDetailsService. A mi CustomAuthenticationFailureHandler a 4.2. példa mutatja.:

4.2. Példa - CustomAuthenticationFailureHandler:

@Component public class CustomAuthenticationFailureHandler kiterjeszti a SimpleUrlAuthenticationFailureHandler {@Autowired private MessageSource üzeneteket; @Autowired private LocaleResolver localeResolver; @Override public void onAuthenticationFailure (HttpServletRequest kérés, HttpServletResponse válasz, AuthenticationException kivétel) dobja az IOException, ServletException {setDefaultFailureUrl ("/ login.html? Error = true"); super.onAuthenticationFailure (kérés, válasz, kivétel); Locale locale = localeResolver.resolveLocale (kérés); String errorMessage = üzenetek.getMessage ("message.badCredentials", null, területi beállítás); if (kivétel.getMessage (). equalsIgnoreCase ("A felhasználó le van tiltva")) {errorMessage = messages.getMessage ("auth.message.disabled", null, locale); } else if (kivétel.getMessage (). equalsIgnoreCase ("A felhasználói fiók lejárt")) {errorMessage = messages.getMessage ("auth.message.expired", null, locale); } request.getSession (). setAttribute (WebAttributes.AUTHENTICATION_EXCEPTION, errorMessage); }}

Módosítanunk kell login.html a hibaüzenetek megjelenítéséhez.

4.3. Példa - Hibaüzenetek megjelenítése itt: login.html:

 hiba 

5. A perzisztencia réteg adaptálása

Most adjuk meg ezeknek a műveleteknek a tényleges végrehajtását, beleértve az ellenőrző tokent és a felhasználókat is.

Kitérünk:

  1. Egy új VerificationTokenRepository
  2. Új módszerek a IUserInterface és az új CRUD műveletek végrehajtásához szükséges

5.1 - 5.3. Példák mutassa meg az új interfészeket és megvalósítást:

5.1. Példa - A VerificationTokenRepository

nyilvános felület A VerificationTokenRepository kiterjeszti a JpaRepository {VerificationToken findByToken (String token); VerificationToken findByUser (felhasználói felhasználó); }

5.2. Példa - A IUserService Felület

nyilvános felület IUserService {Felhasználói regisztrációNewUserAccount (UserDto userDto) dobja UserAlreadyExistException; GetUser (String verificationToken) felhasználó; void saveRegisteredUser (felhasználói felhasználó); void createVerificationToken (Felhasználó felhasználó, String token); VerificationToken getVerificationToken (String VerificationToken); }

5.3. Példa A UserService

@Service @Transactional public class A UserService megvalósítja az IUserService {@Autowired private UserRepository adattárat; @Autowired private VerificationTokenRepository tokenRepository; @Orride public user registerNewUserAccount (UserDto userDto) dobja a UserAlreadyExistException {if (emailExist (userDto.getEmail ()))) {dobjon új UserAlreadyExistException ("Van egy fiók azzal az e-mail címmel:" + userDto.getEmail ()); } Felhasználó felhasználó = új Felhasználó (); user.setFirstName (userDto.getFirstName ()); user.setLastName (userDto.getLastName ()); user.setPassword (userDto.getPassword ()); user.setEmail (userDto.getEmail ()); user.setRole (új szerep (Integer.valueOf (1), felhasználó)); return repository.save (felhasználó); } privát logikai e-mailExist (karakterlánc e-mail) {return userRepository.findByEmail (email)! = null; } @ Felülbírálja a nyilvános felhasználót getUser (Karakterlánc-ellenőrzésToken) {Felhasználó-felhasználó = tokenRepository.findByToken (igazolásToken) .getUser (); visszatérő felhasználó; } @Orride public VerificationToken getVerificationToken (String VerificationToken) {return tokenRepository.findByToken (VerificationToken); } @Orride public void saveRegisteredUser (Felhasználói felhasználó) {repository.save (felhasználó); } @Orride public void createVerificationToken (Felhasználó felhasználó, String token) {VerificationToken myToken = új VerificationToken (token, felhasználó); tokenRepository.save (myToken); }}

6. Következtetés

Ebben a cikkben kibővítettük a regisztráció folyamatát e-mail alapú fiókaktiválási eljárás.

A fiók aktiválási logikája megköveteli, hogy e-mailben küldjön egy ellenőrző tokent a felhasználónak, hogy az visszaküldhesse a vezérlőnek személyazonosságának igazolására.

Ennek a regisztrációnak a Spring Security oktatóanyagának a megvalósítása megtalálható a GitHub projektben - ez egy Eclipse alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.

Következő » Tavaszi biztonsági regisztráció - Ellenőrző e-mail újraküldése « Előző a regisztráció folyamata a tavaszi biztonsággal