Spring Security - אפס את הסיסמה שלך

מאמר זה הוא חלק מסדרה: • מדריך רישום אבטחה באביב

• תהליך ההרשמה עם אבטחת אביב

• הרשמה - הפעל חשבון חדש בדוא"ל

• רישום אבטחה באביב - שלח שוב דוא"ל אימות

• הרשמה באבטחת אביב - קידוד סיסמאות

• ממשק ה- API לרישום הופך ל- RESTful

• אבטחת אביב - אפס את הסיסמה שלך (מאמר נוכחי) • הרשמה - חוזק סיסמא וכללים

• עדכון הסיסמה שלך

1. סקירה כללית

במדריך זה - אנו ממשיכים בהמשך הרשמה באביב ביטחון סִדרָה במבט על הבסיס "שכחתי את הסיסמא שליתכונה - כדי שהמשתמש יוכל לאפס את הסיסמה שלו בבטחה בעת הצורך.

2. בקש לאפס את הסיסמה שלך

זרימת איפוס סיסמה מתחילה בדרך כלל כאשר המשתמש לוחץ על איזשהו כפתור "איפוס" בדף הכניסה. לאחר מכן נוכל לבקש מהמשתמש את כתובת הדוא"ל שלו או מידע מזהה אחר. לאחר האישור, אנו יכולים ליצור אסימון ולשלוח דוא"ל למשתמש.

התרשים הבא מדגים את הזרימה שניישם במאמר זה:

3. אסימון איפוס הסיסמה

נתחיל ביצירת a PasswordResetToken ישות שתשתמש בו לאיפוס סיסמת המשתמש:

מחלקה ציבורית @Entity PasswordResetToken {סופי פרטי סטטי int EXPIRATION = 60 * 24; @Id @GeneratedValue (אסטרטגיה = GenerationType.AUTO) מזהה פרטי ארוך; אסימון מחרוזת פרטי; @OneToOne (targetEntity = User.class, fetch = FetchType.EAGER) @JoinColumn (nullable = false, name = "user_id") משתמש משתמש פרטי; תאריך תפוגה פרטי תאריך פרטי; }

כאשר מופעל איפוס סיסמא - ייווצר אסימון ו קישור מיוחד המכיל אסימון זה יישלח בדוא"ל למשתמש.

האסימון והקישור יהיו תקפים לפרק זמן מוגדר בלבד (24 שעות בדוגמה זו).

4. forgotPassword.html

העמוד הראשון בתהליך הוא ה "שכחתי את הסיסמא שלי" עמוד - שם המשתמש מתבקש להזין את כתובת הדוא"ל שלו על מנת שתהליך האיפוס בפועל יתחיל.

אז - בואו נעשה פשוט forgotPassword.html מבקש מהמשתמש כתובת דוא"ל:

אִתחוּל

איפוס דוא"ל התחברות לרישום var serverContext = [[@ {/}]]; function resetPass () {var email = $ ("# email"). val (); $ .post (serverContext + "user / resetPassword", {email: email}, function (data) {window.location.href = serverContext + "login? message =" + data.message;}) .fail (function (data) ) {אם (data.responseJSON.error.indexOf ("MailError")> -1) {window.location.href = serverContext + "emailError.html";} אחר {window.location.href = serverContext + "הודעת כניסה? = "+ data.responseJSON.message;}}); }

כעת עלינו לקשר לקשר החדש הזה "לאפס את הסיסמהמדף הכניסה:

אִתחוּל

5. צור את ה- PasswordResetToken

נתחיל ביצירת החדש PasswordResetToken ולשלוח אותו בדוא"ל למשתמש:

@PostMapping ("/ user / resetPassword") ציבורי GenericResponse resetPassword (HttpServletRequest בקשה, @RequestParam ("דוא"ל") מחרוזת userEmail) {User user = userService.findUserByEmail (userEmail); אם (user == null) {זרוק UserNotFoundException חדש (); } אסימון מחרוזת = UUID.randomUUID (). ToString (); userService.createPasswordResetTokenForUser (משתמש, אסימון); mailSender.send (constructResetTokenEmail (getAppUrl (בקשה), request.getLocale (), אסימון, משתמש)); להחזיר GenericResponse חדש (messages.getMessage ("message.resetPasswordEmail", null, request.getLocale ())); }

והנה ה createPasswordResetTokenForUser () שיטה:

בטל ציבורי createPasswordResetTokenForUser (משתמש משתמש, אסימון מחרוזת) {PasswordResetToken myToken = PasswordResetToken חדש (אסימון, משתמש); passwordTokenRepository.save (myToken); }

והנה שיטה constructResetTokenEmail () - משמש לשלוח דוא"ל עם אסימון האיפוס:

פרטי SimpleMailMessage constructResetTokenEmail (String contextPath, Locale locale, String token, User user) {String url = contextPath + "/ user / changePassword? token =" + token; הודעת מחרוזת = messages.getMessage ("message.resetPassword", null, locale); להחזיר constructEmail ("אפס סיסמה", הודעה + "\ r \ n" + url, משתמש); } פרטי SimpleMailMessage buildEmail (נושא מחרוזת, גוף מחרוזת, משתמש משתמש) {SimpleMailMessage email = new SimpleMailMessage (); email.setSubject (נושא); email.setText (גוף); email.setTo (user.getEmail ()); email.setFrom (env.getProperty ("support.email")); החזרת דוא"ל; }

שימו לב כיצד השתמשנו באובייקט פשוט תגובה Generic לייצג את תגובתנו ללקוח:

מחלקה ציבורית GenericResponse {הודעת מחרוזת פרטית; שגיאת מחרוזת פרטית; GenericResponse ציבורי (הודעת מחרוזת) {super (); הודעה זו = הודעה; } GenericResponse ציבורי (הודעת מחרוזת, שגיאת מחרוזת) {super (); הודעה זו = הודעה; this.error = שגיאה; }}

6. בדוק את PasswordResetToken

ברגע שהמשתמש לוחץ על הקישור בדוא"ל שלו, ה- משתמש / changePassword נקודת סיום:

  • מאמת שהאסימון תקף ו
  • מציג למשתמש את ה- עדכן סיסמה דף, שבו הוא יכול להזין סיסמה חדשה

הסיסמה החדשה והאסימון מועברים אל ה- משתמש / שמור סיסמה נקודת סיום:

המשתמש מקבל את הדוא"ל עם הקישור הייחודי לאיפוס הסיסמה שלו, ולחץ על הקישור:

@GetMapping ("/ user / changePassword") ציבורי מחרוזת showChangePasswordPage (אזור אזור, מודל מודל, @RequestParam ("אסימון") אסימון מחרוזת) {מחרוזת תוצאה = securityService.validatePasswordResetToken (אסימון); if (result! = null) {String message = messages.getMessage ("auth.message." + result, null, locale); להחזיר "redirect: /login.html? lang =" + locale.getLanguage () + "& message =" + message; } אחר {model.addAttribute ("אסימון", אסימון); להחזיר "redirect: /updatePassword.html? lang =" + locale.getLanguage (); }}

והנה ה validatePasswordResetToken () שיטה:

validatePasswordResetToken (מחרוזת מחרוזת) ציבורי ציבורי {final PasswordResetToken passToken = passwordTokenRepository.findByToken (token); להחזיר! isTokenFound (passToken)? "invalidToken": isTokenExpired (passToken)? "פג תוקף": null; } isTokenFound בוליאני פרטי (PasswordResetToken passToken) {להחזיר passToken! = null; } isTokenExpired בוליאני פרטי (PasswordResetToken passToken) {לוח שנה אחרון cal = Calendar.getInstance (); החזר את passToken.getExpiryDate (). לפני (cal.getTime ()); }

7. שנה את הסיסמה

בשלב זה, המשתמש רואה את הפשוט איפוס סיסמא דף - היכן שהאפשרות היחידה היא ספק סיסמה חדשה:

7.1. updatePassword.html

אִתחוּל

סיסמה אישר שגיאה אסימונית שלח var serverContext = [[@ {/}]]; $ (document) .ready (function () {$ ('form'). submit (function (event) {savePass (event);}); $ (": password"). keyup (function () {if ($ ("# סיסמה"). val ()! = $ ("# matchPassword"). val ()) {$ ("# globalError"). show (). html (/ * [[# {PasswordMatches.user}] ] * /);} אחר {$ ("# globalError"). html (""). להסתיר ();}});}); function savePass (event) {event.preventDefault (); if ($ ("# password"). val ()! = $ ("# matchPassword"). val ()) {$ ("# globalError"). show (). html (/ * [[# {PasswordMatches. מִשׁתַמֵשׁ}]]*/); לַחֲזוֹר; } var formData = $ ('טופס'). סידור (); $ .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;} אחר {var שגיאות = $ .parseJSON (נתונים. responseJSON.message); $ .each (שגיאות, פונקציה (אינדקס, פריט) {$ ("# globalError"). show (). html (item.defaultMessage);}); שגיאות = $ .parseJSON (data.responseJSON. שגיאה); $ .each (שגיאות, פונקציה (אינדקס, פריט) {$ ("# globalError"). show (). append (item.defaultMessage + "

"); }); } }); }

שים לב שאנו מציגים את אסימון האיפוס ומעבירים אותו כפרמטר POST בשיחה הבאה כדי לשמור את הסיסמה.

7.2. שמור את הסיסמה

לבסוף, כאשר מוגשת בקשת ההודעה הקודמת - נשמרת סיסמת המשתמש החדשה:

@PostMapping ("/ user / savePassword") ציבורי GenericResponse savePassword (האזור הסופי של המקום, @Valid PasswordDto passwordDto) {מחרוזת תוצאה = securityUserService.validatePasswordResetToken (passwordDto.getToken ()); אם (תוצאה! = null) {להחזיר GenericResponse חדש (messages.getMessage ("auth.message." + תוצאה, null, locale)); } משתמש אופציונלי = userService.getUserByPasswordResetToken (passwordDto.getToken ()); אם (user.isPresent ()) {userService.changeUserPassword (user.get (), passwordDto.getNewPassword ()); להחזיר GenericResponse חדש (messages.getMessage ("message.resetPasswordSuc", null, locale)); } אחר {להחזיר GenericResponse חדש (messages.getMessage ("auth.message.invalid", null, locale)); }}

והנה ה changeUserPassword () שיטה:

שינוי חלל ציבורי UserPassword (משתמש משתמש, סיסמת מחרוזת) {user.setPassword (passwordEncoder.encode (סיסמה)); repository.save (משתמש); }

וה PasswordDto:

מחלקה ציבורית PasswordDto {פרטי מחרוזת oldPassword; אסימון מחרוזת פרטי; @ValidPassword פרטי מחרוזת newPassword; } 

8. מסקנה

במאמר זה יישמנו תכונה פשוטה אך שימושית מאוד לתהליך אימות בוגר - אפשרות לאיפוס הסיסמה שלך, כמשתמש במערכת.

ה יישום מלא של מדריך זה ניתן למצוא בפרויקט GitHub - זהו פרויקט מבוסס Eclipse, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.

הַבָּא » רישום - חוזק סיסמאות וכללים « קודם ממשק ה- API לרישום הופך ל- RESTful

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