Proces registracije s proljetnom sigurnošću
• Postupak registracije s proljetnom sigurnošću (trenutni članak) • Registracija - Aktivirajte novi račun e-poštom
• Proljetna sigurnosna registracija - ponovno pošaljite e-poštu za potvrdu
• Registracija s Spring Security - kodiranje lozinkom
• API za registraciju postaje RESTful
• Proljetna sigurnost - resetirajte lozinku
• Registracija - Snaga lozinke i pravila
• Ažuriranje lozinke
1. Pregled
U ovom ćemo članku implementirati osnovni postupak registracije u Spring Security. Ovo se nadovezuje na koncepte istražene u prethodnom članku, gdje smo pogledali prijavu.
Ovdje je cilj dodati puni postupak registracije koji omogućuje korisniku da se prijavi, provjeri valjanost i ustraje u korisničkim podacima.
2. Stranica za registraciju
Prvo - implementiramo jednostavno prikazivanje stranice za registraciju sljedeća polja:
- Ime (ime i prezime)
- zaporka (i polje za potvrdu lozinke)
Sljedeći primjer pokazuje jednostavan registracija.html stranica:
Primjer 2.1.
oblik
prvi Pogreška provjere
posljednji Pogreška provjere
e-mail Pogreška provjere
zaporka Pogreška provjere
potvrdi prijava prijava
3.Korisnički DTO objekt
Trebamo Objekt prijenosa podataka za slanje svih podataka o registraciji na naš proljetni backend. The DTO Objekt bi trebao imati sve podatke koji će nam biti potrebni kasnije kada kreiramo i popunimo svoj Korisnik objekt:
javna klasa UserDto {@NotNull @NotEmpty private String firstName; @NotNull @NotEmpty privatni niz lastName; @NotNull @NotEmpty lozinka privatnog niza; private String matchingPassword; @NotNull @NotEmpty privatni niz e-pošte; // standardni geteri i postavljači}
Primijetimo da smo koristili standard javax.valifikacija napomene na poljima DTO objekta. Kasnije ćemo također implementirati vlastite napomene o provjeri valjanosti za provjeru formata adrese e-pošte, kao i za potvrdu lozinke. (vidjeti Odjeljak 5)
4. Kontrolor registracije
A Prijava link na prijaviti se stranica odvest će korisnika na registracija stranica. Ovaj zadnji kraj te stranice živi u upravljaču za registraciju i preslikava se na "/Registracija korisnika":
Primjer 4.1. - The showRegistracija Metoda
@GetMapping ("/ korisnik / registracija") javni niz showRegistrationForm (zahtjev web-zahtjeva, model modela) {UserDto userDto = new UserDto (); model.addAttribute ("korisnik", userDto); vratiti "registraciju"; }
Kad kontrolor primi zahtjev "/Registracija korisnika", stvara novo UserDto objekt koji će podržati registracija oblik, veže ga i vraća - prilično izravno.
5. Provjera valjanosti podataka o registraciji
Dalje - pogledajmo provjere valjanosti koje će kontroler izvršiti prilikom registracije novog računa:
- Sva obavezna polja su popunjena (Nema praznih ili nula polja)
- Adresa e-pošte je valjana (dobro oblikovana)
- Polje za potvrdu lozinke podudara se s poljem lozinke
- Račun već ne postoji
5.1. Ugrađena provjera valjanosti
Za jednostavne provjere upotrijebit ćemo napomene za provjeru graha izvan okvira na DTO objektu - bilješke poput @NotNull, @Nije praznoitd.
Da bismo pokrenuli postupak provjere valjanosti, jednostavno ćemo objekt u sloju kontrolera označiti znakom @Valid napomena:
javni ModelAndView registerUserAccount (@ModelAttribute ("korisnik") @Valid UserDto userDto, zahtjev HttpServletRequest, pogreške u pogreškama) {...}
5.2. Prilagođena provjera valjanosti za provjeru valjanosti e-pošte
Dalje - provjerimo valjanost adrese e-pošte i pobrinimo se da je dobro oblikovana. Gradit ćemo a prilagođeni validator za to, kao i napomena prilagođene provjere valjanosti - nazovimo to @ValidEmail.
Ovdje na brzinu - uvodimo vlastitu prilagođenu napomenu umjesto hibernatskog@E-mail jer Hibernate uzima u obzir stari format adresa intraneta: [e-pošta zaštićena] kao valjano (vidi članak Stackoverflow), što nije dobro.
Evo bilješke o provjeri valjanosti e-pošte i prilagođenog programa za provjeru valjanosti:
Primjer 5.2.1. - Prilagođena bilješka za provjeru valjanosti e-pošte
@Target ({TYPE, FIELD, ANNOTATION_TYPE}) @Retention (RUNTIME) @Constraint (validatedBy = EmailValidator.class) @Documented public @interface ValidEmail {String message () default "Invalid email"; Class [] groups () zadani {}; Klasa [] korisni teret () zadana {}; }
Imajte na umu da smo napomenu definirali na POLJE razina - budući da se tu primjenjuje konceptualno.
Primjer 5.2.2. - Običaj EmailValidator:
javna klasa EmailValidator implementira ConstraintValidator {privatni obrazac uzorka; privatno podudaranje Matchera; privatni statički završni niz EMAIL_PATTERN = "^ [_ A-Za-z0-9 - +] + (. [_ A-Za-z0-9 -] +) * @" + "[A-Za-z0-9 -] + (. [A-Za-z0-9] +) * (. [A-Za-z-z] {2,}) $ "; @Override javna void inicijalizacija (ValidEmail constraintAnnotation) {} @Override public boolean isValid (String email, ConstraintValidatorContext context) {return (validateEmail (email)); } privatna logička validateEmail (string e-pošte) {pattern = Pattern.compile (EMAIL_PATTERN); podudaranje = pattern.matcher (e-pošta); vratiti matcher.matches (); }}
Idemo sada upotrijebi novu napomenu na naš UserDto provedba:
@ValidEmail @NotNull @NotEmpty e-mail privatnog niza;
5.3. Korištenje prilagođene provjere valjanosti za potvrdu lozinke
Također trebamo prilagođenu napomenu i validator kako bismo bili sigurni da zaporka i odgovarajuća lozinka polja se podudaraju:
Primjer 5.3.1. - Prilagođena bilješka za provjeru potvrde lozinke
@Target ({TYPE, ANNOTATION_TYPE}) @Retention (RUNTIME) @Constraint (validatedBy = PasswordMatchesValidator.class) @Documented public @interface PasswordMatches {String message () default "Lozinke se ne podudaraju"; Class [] groups () zadani {}; Klasa [] korisni teret () zadana {}; }
Primijetite da @Cilj napomena označava da je ovo a TIP bilješka na razini. To je zato što nam treba cjelokupno UserDto objekt koji će izvršiti provjeru valjanosti.
Prilagođeni validator koji će biti pozvan ovom bilješkom prikazan je u nastavku:
Primjer 5.3.2. The PasswordMatchesValidator Prilagođeni validator
javna klasa PasswordMatchesValidator implementira ConstraintValidator {@Override javna void inicijalizacija (PasswordMatches constraintAnnotation) {} @Override javni boolean isValid (Object obj, ConstraintValidatorContext context) {UserDto user = (UserDto) obj; vrati user.getPassword (). jednako (user.getMatchingPassword ()); }}
Sada, @PasswordMatches napomenu treba primijeniti na naš UserDto objekt:
@PasswordMatches javne klase UserDto {...}
Sve se prilagođene provjere valjanosti vrednuju zajedno sa svim standardnim bilješkama kada se pokrene cijeli postupak provjere valjanosti.
5.4. Provjerite da račun već ne postoji
Četvrta provjera koju ćemo provesti je provjera da li e-mail račun već ne postoji u bazi podataka.
To se izvodi nakon što je obrazac potvrđen i to je učinjeno uz pomoć Korisnička usluga provedba.
Primjer 5.4.1. - Kontrolorov createUserAccount Metoda poziva Korisnička usluga Objekt
@PostMapping ("/ user / registration") public ModelAndView registerUserAccount (@ModelAttribute ("user") @Valid UserDto userDto, HttpServletRequest zahtjev, pogreške pogrešaka) {try {User registered = userService.registerNewUserAccount (userDto); } catch (UserAlreadyExistException uaeEx) {mav.addObject ("message", "Račun za to korisničko ime / e-adresu već postoji."); povratak mav; } // ostatak implementacije}
Primjer 5.4.2. - KorisnikServis Provjerava duplicirane e-adrese
@Service javna klasa UserService implementira IUserService {@Autowired privatno spremište UserRepository; @Transactional @Override public User registerNewUserAccount (UserDto userDto) baca UserAlreadyExistException {if (emailExist (userDto.getEmail ())) {throw new UserAlreadyExistException ("Postoji račun s tom adresom e-pošte:" + userDto.getEmail); } ... // ostatak postupka registracije} private boolean emailExist (String email) {return userRepository.findByEmail (email)! = null; }}
UserService oslanja se na UserRepository klase da provjeri postoji li korisnik s danom adresom e-pošte u bazi podataka.
Sada - stvarna provedba UserRepository u sloju postojanosti nije relevantan za trenutni članak. Jedan od brzih načina je, naravno, korištenje Spring Data za generiranje sloja spremišta. Na kraju - implementiramo logiku registracije u naš sloj kontrolera: Primjer 6.1.1. - The Registrirajte račun Metoda u kontroleru Stvari koje treba primijetiti u gornjem kodu: Završimo provedbu postupka registracije u Korisnička usluga: Primjer 7.1. The IUserService Sučelje Primjer 7.2. - The Korisnička usluga Razred U našem prethodnom članku prijava je koristila tvrdo kodirane vjerodajnice. Promijenimo to i koristiti novoregistrirane korisničke podatke i vjerodajnice. Primijenit ćemo običaj UserDetailsService za provjeru vjerodajnica za prijavu iz sloja postojanosti. Počnimo s implementacijom usluge prilagođenih korisničkih podataka: Da bismo omogućili novu korisničku uslugu u konfiguraciji Spring Security - jednostavno moramo dodati referencu na UserDetailsService unutar autentifikacija-upravitelj element i dodajte UserDetailsService grah: Primjer 8.2.- Upravitelj provjere autentičnosti i UserDetailsService Ili putem Java konfiguracije: I gotovi smo - potpuno i gotovo postupak registracije spreman za proizvodnju implementiran s Spring Security i Spring MVC. Dalje ćemo razgovarati o procesu aktiviranja novoregistriranog računa provjerom e-pošte novog korisnika. Implementaciju ovog vodiča Spring REST možete pronaći u projektu GitHub - ovo je projekt zasnovan na Eclipseu, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.6. Trajna obrada podataka i dorada obrazaca
@PostMapping ("/ user / registration") public ModelAndView registerUserAccount (@ModelAttribute ("user") @Valid UserDto userDto, HttpServletRequest zahtjev, pogreške pogrešaka) {try {User registered = userService.registerNewUserAccount (userDto); } catch (UserAlreadyExistException uaeEx) {mav.addObject ("message", "Račun za to korisničko ime / e-adresu već postoji."); povratak mav; } vratiti novi ModelAndView ("successRegister", "user", userDto); }
7.The Korisnička usluga - Registrirajte rad
javno sučelje IUserService {User registerNewUserAccount (UserDto userDto) baca UserAlreadyExistException; }
@Service javna klasa UserService implementira IUserService {@Autowired privatno spremište UserRepository; @Transactional @Override public User registerNewUserAccount (UserDto userDto) baca UserAlreadyExistException {if (emailExists (userDto.getEmail ())) {throw new UserAlreadyExistException ("Postoji račun s tom adresom e-pošte: + userDto.getEmail ();) user = new User (); user.setFirstName (userDto.getFirstName ()); user.setLastName (userDto.getLastName ()); user.setPassword (userDto.getPassword ()); user.setEmail (userDto.getEmail ()) ; user.setRoles (Arrays.asList ("ROLE_USER")); return repository.save (user);} private boolean emailExists (String email) {return userRepository.findByEmail (email)! = null;}}
8. Učitavanje korisničkih podataka za sigurnosnu prijavu
8.1. Običaj UserDetailsService
@Service @Transactional javna klasa MyUserDetailsService implementira UserDetailsService {@Autowired private UserRepository userRepository; // javni UserDetails loadUserByUsername (String e-mail) baca UsernameNotFoundException {User user = userRepository.findByEmail (email); if (user == null) {throw new UsernameNotFoundException ("Nije pronađen nijedan korisnik s korisničkim imenom:" + e-pošta); } logička vrijednost = true; boolean accountNonExpired = true; logičke vjerodajniceNonExpired = true; boolean accountNonLocked = true; vrati novi org.springframework.security.core.userdetails.User (user.getEmail (), user.getPassword (). toLowerCase (), enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities (user.getRoles ())); } privatni statički popis getAuthorities (uloge popisa) {Ovlasti popisa = novi ArrayList (); za (uloga u nizu: uloge) {Authority.add (nova SimpleGrantedAuthority (uloga)); } vlasti za povratak; }}
8.2. Omogućite novog davatelja autentičnosti
@Autowired private MyUserDetailsService userDetailsService; @Override zaštićena void konfiguracija (AuthenticationManagerBuilder auth) baca iznimku {auth.userDetailsService (userDetailsService); }
9. Zaključak