Jarná bezpečnosť - obnovte svoje heslo

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

• 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

• Zabezpečenie na jar - obnovenie hesla (aktuálny článok) • Registrácia - sila a pravidlá hesla

• Aktualizácia hesla

1. Prehľad

V tomto výučbe pokračujeme ďalej Registrácia s jarným zabezpečením série s pohľadom na základ "Zabudol som svoje heslo”Funkcia - aby si používateľ mohol v prípade potreby bezpečne resetovať svoje vlastné heslo.

2. Požiadajte o obnovenie hesla

Postup obnovenia hesla sa zvyčajne spustí, keď používateľ klikne na akési tlačidlo „resetovať“ na prihlasovacej stránke. Potom môžeme používateľa požiadať o jeho e-mailovú adresu alebo iné identifikačné údaje. Po potvrdení môžeme vygenerovať token a poslať e-mail používateľovi.

Nasledujúci diagram vizualizuje tok, ktorý implementujeme v tomto článku:

3. Token na obnovenie hesla

Začnime vytvorením PasswordResetToken subjekt, ktorý ho použije na obnovenie hesla používateľa:

@Entity verejná trieda PasswordResetToken {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; }

Keď sa aktivuje obnovenie hesla - vytvorí sa token a užívateľovi bude zaslaný špeciálny odkaz obsahujúci tento token.

Token a odkaz budú platné iba po stanovenú dobu (v tomto príklade 24 hodín).

4. zabudnuté heslo.html

Prvá stránka v tomto procese je Zabudol som svoje heslo - kde je používateľ vyzvaný na zadanie svojej e-mailovej adresy, aby mohol začať skutočný proces resetovania.

Takže - poďme si vyrobiť jednoduché zabudnuté heslo.html požiadanie používateľa o e-mailovú adresu:

resetovať

e-mail reset registrácia prihlásenie var serverContext = [[@ {/}]]; funkcia resetPass () {var email = $ ("# email"). val (); $ .post (serverContext + "user / resetPassword", {email: email}, function (data) {window.location.href = serverContext + "login? message =" + data.message;}) .fail (funkcia (data ) {if (data.responseJSON.error.indexOf ("MailError")> -1) {window.location.href = serverContext + "emailError.html";} else {window.location.href = serverContext + "prihlásiť? správa = "+ data.responseJSON.message;}}); }

Teraz musíme prepojiť tento nový „obnoviť heslo”Stránka z prihlasovacej stránky:

resetovať

5. Vytvorte PasswordResetToken

Začnime tvorbou nového PasswordResetToken a pošlite ho e-mailom používateľovi:

@PostMapping ("/ user / resetPassword") verejné GenericResponse resetPassword (požiadavka HttpServletRequest, @RequestParam ("email") reťazec userEmail) {User user = userService.findUserByEmail (userEmail); if (user == null) {throw new UserNotFoundException (); } Token reťazca = UUID.randomUUID (). ToString (); userService.createPasswordResetTokenForUser (užívateľ, token); mailSender.send (constructResetTokenEmail (getAppUrl (požiadavka), request.getLocale (), token, užívateľ)); vrátiť nový GenericResponse (messages.getMessage ("message.resetPasswordEmail", null, request.getLocale ())); }

A tu je createPasswordResetTokenForUser () metóda:

public void createPasswordResetTokenForUser (užívateľský užívateľ, token reťazca) {PasswordResetToken myToken = nový PasswordResetToken (token, užívateľ); passwordTokenRepository.save (myToken); }

A tu je metóda constructResetTokenEmail () - slúži na odoslanie e-mailu s obnovovacím tokenom:

private SimpleMailMessage constructResetTokenEmail (String contextPath, locale locale, String token, User user) {String url = contextPath + "/ user / changePassword? token =" + token; Reťazec message = messages.getMessage ("message.resetPassword", null, miestne nastavenie); return constructEmail ("Obnoviť heslo", správa + "\ r \ n" + url, užívateľ); } private SimpleMailMessage constructEmail (predmet reťazca, telo reťazca, používateľ používateľa) {SimpleMailMessage email = nový SimpleMailMessage (); email.setSubject (predmet); email.setText (telo); email.setTo (user.getEmail ()); email.setFrom (env.getProperty ("support.email")); spätný e-mail; }

Všimnite si, ako sme použili jednoduchý objekt Generická odpoveď zastupovať našu odpoveď klientovi:

public class GenericResponse {private String message; chyba súkromného reťazca; public GenericResponse (reťazcová správa) {super (); this.message = správa; } public GenericResponse (String message, String error) {super (); this.message = správa; this.error = chyba; }}

6. Skontrolujte PasswordResetToken

Akonáhle užívateľ klikne na odkaz vo svojom e-maile, user / changePassword koncový bod:

  • overí, či je token platný a
  • predstavuje používateľovi aktualizovať heslo stránku, kde môže zadať nové heslo

Nové heslo a token sa potom odovzdajú serveru pouzivatel / savePassword koncový bod:

Používateľ dostane e-mail s jedinečným odkazom na obnovenie hesla a klikne na odkaz:

@GetMapping ("/ user / changePassword") public String showChangePasswordPage (miestne nastavenie, model modelu, @RequestParam ("token") reťazec token) {Výsledok reťazca = securityService.validatePasswordResetToken (token); if (result! = null) {String message = messages.getMessage ("auth.message." + result, null, locale); return "redirect: /login.html? lang =" + locale.getLanguage () + "& message =" + správa; } else {model.addAttribute ("token", token); return "redirect: /updatePassword.html? lang =" + locale.getLanguage (); }}

A tu je validatePasswordResetToken () metóda:

public String validatePasswordResetToken (reťazec token) {final PasswordResetToken passToken = hesloTokenRepository.findByToken (token); návrat! isTokenFound (passToken)? "invalidToken": isTokenExpired (passToken)? "expired": null; } private boolean isTokenFound (PasswordResetToken passToken) {return passToken! = null; } private boolean isTokenExpired (PasswordResetToken passToken) {final Calendar cal = Calendar.getInstance (); return passToken.getExpiryDate (). before (cal.getTime ()); }

7. Zmeňte heslo

V tomto okamihu vidí užívateľ jednoduché Resetovanie hesla stránka - kde je jediná možná možnosť zadajte nové heslo:

7.1. updatePassword.html

resetovať

heslo potvrdiť chybu tokenu odoslať var serverContext = [[@ {/}]]; $ (document) .ready (function () {$ ('form'). submit (function (event) {savePass (event);}); $ (": password"). keyup (function () {if ($ ("#password"). val ()! = $ ("# matchPassword"). val ()) {$ ("# globalError"). show (). html (/ * [[# # PasswordMatches.user}] ] * /);} else {$ ("# globalError"). html (""). hide ();}});}); funkcia savePass (event) {event.preventDefault (); if ($ ("# heslo"). val ()! = $ ("# matchPassword"). val ()) {$ ("# globalError"). show (). html (/ * [[# {PasswordMatches. používateľ}]] * /); návrat; } var formData = $ ('form'). serialize (); $ .post (serverContext + "user / savePassword", formData, function (data) {window.location.href = serverContext + "login? message =" + data.message;}) .fail (function (data) {if ( data.responseJSON.error.indexOf ("InternalError")> -1) {window.location.href = serverContext + "login? message =" + data.responseJSON.message;} else {var errors = $ .parseJSON (data. responseJSON.message); $ .each (errors, function (index, item) {$ ("# globalError"). show (). html (item.defaultMessage);}); errors = $ .parseJSON (data.responseJSON. chyba); $ .each (chyby, funkcia (index, položka) {$ ("# globalError"). show (). append (item.defaultMessage + "

"); }); } }); }

Upozorňujeme, že obnovovací token ukážeme a v nasledujúcom hovore ho odovzdáme ako parameter POST na uloženie hesla.

7.2. Uložte heslo

Nakoniec, keď je odoslaná predchádzajúca žiadosť o príspevok - nové heslo používateľa sa uloží:

@PostMapping ("/ user / savePassword") public GenericResponse savePassword (konečné miestne nastavenie, @Valid PasswordDto hesloDto) {Výsledok reťazca = securityUserService.validatePasswordResetToken (hesloDto.getToken ()); if (result! = null) {return new GenericResponse (messages.getMessage ("auth.message." + result, null, locale)); } Voliteľný užívateľ = userService.getUserByPasswordResetToken (passwordDto.getToken ()); if (user.isPresent ()) {userService.changeUserPassword (user.get (), passwordDto.getNewPassword ()); vrátiť nový GenericResponse (messages.getMessage ("message.resetPasswordSuc", null, locale)); } else {navrat novu GenericResponse (messages.getMessage ("auth.message.invalid", null, locale)); }}

A tu je changeUserPassword () metóda:

public void changeUserPassword (používateľský používateľ, heslo reťazca) {user.setPassword (hesloEncoder.encode (heslo)); repository.save (užívateľ); }

A Heslo Dto:

verejná trieda PasswordDto {private String oldPassword; súkromný reťazcový token; @ValidPassword private String newPassword; } 

8. Záver

V tomto článku sme implementovali jednoduchú, ale veľmi užitočnú funkciu pre vyspelý proces autentifikácie - možnosť resetovať svoje vlastné heslo ako používateľ systému.

The úplná implementácia tohto tutoriálu 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 » Registrácia - sila hesla a pravidlá « Predchádzajúci Registračné API sa stáva RESTful

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