Registreringsprocessen med forårssikkerhed

Denne artikel er en del af en serie: • Vejledning i Spring Security Registration

• Registreringsprocessen med Spring Security (nuværende artikel) • Registrering - Aktiver en ny konto via e-mail

• Forårsikkerhedsregistrering - Send bekræftelses-e-mail igen

• Registrering med Spring Security - kodning af adgangskode

• Registrerings-API'en bliver RESTful

• Spring Security - Nulstil din adgangskode

• Registrering - adgangskodestyrke og regler

• Opdatering af din adgangskode

1. Oversigt

I denne artikel implementerer vi en grundlæggende registreringsproces med Spring Security. Dette bygger på de begreber, der blev undersøgt i den forrige artikel, hvor vi kiggede på login.

Målet her er at tilføje en fuld registreringsproces der gør det muligt for en bruger at tilmelde sig, validerer og vedvarer brugerdata.

2. Registreringssiden

Først - lad os implementere en simpel registreringsside, der vises følgende felter:

  • navn (for-og efternavn)
  • e-mail
  • adgangskode (og bekræftelsesfelt for adgangskode)

Følgende eksempel viser en simpel registrering.html side:

Eksempel 2.1.

form

først

Valideringsfejl

sidst

Valideringsfejl

e-mail

Valideringsfejl

adgangskode

Valideringsfejl

bekræft indsend login

3.Brugerens DTO-objekt

Vi har brug for en Dataoverførselsobjekt at sende alle registreringsoplysningerne til vores Spring backend. Det DTO objektet skal have alle de oplysninger, vi skal bruge senere, når vi opretter og udfylder vores Bruger objekt:

offentlig klasse UserDto {@NotNull @NotEmpty privat streng fornavn; @NotNull @NotEmpty privat streng efternavn; @NotNull @NotEmpty privat strengadgangskode; private String matchingPassword; @NotNull @NotEmpty privat strengemail; // standard getters og setter}

Bemærk, at vi brugte standard javax.validation bemærkninger på felterne i DTO-objektet. Senere vil vi også implementere vores egne brugerdefinerede valideringsanmærkninger for at validere formatet på e-mail-adressen samt til bekræftelse af adgangskoden. (se Afsnit 5)

4. Registreringscontrolleren

EN Tilmelde link på Log på siden fører brugeren til registrering side. Denne back-end for denne side bor i registreringscontrolleren og er kortlagt til “/ Bruger / registrering”:

Eksempel 4.1. - Det showRegistration Metode

@GetMapping ("/ bruger / registrering") offentlig String showRegistrationForm (WebRequest-anmodning, modelmodel) {UserDto userDto = ny UserDto (); model.addAttribute ("bruger", userDto); returner "registrering" }

Når controlleren modtager anmodningen “/ Bruger / registrering”, det skaber det nye UserDto objekt, der vil bakke op registrering form, binder den og vender tilbage - ret ligetil.

5. Validering af registreringsdata

Dernæst - lad os se på de valideringer, som controlleren udfører, når han registrerer en ny konto:

  1. Alle påkrævede felter er udfyldt (Ingen tomme eller null felter)
  2. E-mail-adressen er gyldig (velformet)
  3. Feltet til bekræftelse af adgangskode matcher feltet for adgangskode
  4. Kontoen findes ikke allerede

5.1. Den indbyggede validering

Til de enkle kontroller bruger vi ud af boksen bønnevalideringsanmærkninger på DTO-objektet - bemærkninger som @NotNull, @NotEmpty, etc.

For at udløse valideringsprocessen annoterer vi blot objektet i controller-laget med @Gyldig kommentar:

offentligt ModelAndView registerUserAccount (@ModelAttribute ("bruger") @Valid UserDto userDto, HttpServletRequest anmodning, fejl fejl) {...}

5.2. Brugerdefineret validering for at kontrollere e-mail-gyldighed

Næste - lad os validere e-mail-adressen og sikre, at den er velformet. Vi skal bygge en brugerdefineret validator for det såvel som en brugerdefineret validering annotation - lad os kalde det @ValidEmail.

En hurtig sidenote her - vi ruller vores egen brugerdefinerede kommentar i stedet for dvale@E-mail fordi dvale overvejer det gamle intranetadresseformat: [e-mail beskyttet] som gyldig (se Stackoverflow-artiklen), hvilket ikke er godt.

Her er e-mail-valideringsannotationen og den brugerdefinerede validator:

Eksempel 5.2.1. - Den brugerdefinerede kommentar til validering af e-mail

@Target ({TYPE, FIELD, ANNOTATION_TYPE}) @Retention (RUNTIME) @Constraint (validatedBy = EmailValidator.class) @Documented public @interface ValidEmail {Strengmeddelelse () standard "Ugyldig e-mail"; Klasse [] grupper () standard {}; Klasse [] nyttelast () standard {}; }

Bemærk, at vi har defineret kommentaren på MARK niveau - da det er her, det gælder konceptuelt.

Eksempel 5.2.2. - Brugeren E-mailValidator:

offentlig klasse EmailValidator implementerer ConstraintValidator {privat mønster mønster; privat Matcher matcher; privat statisk endelig streng EMAIL_PATTERN = "^ [_ A-Za-z0-9 - +] + (. [_ A-Za-z0-9 -] +) * @" + "[A-Za-z0-9 -] + (. [A-Za-z0-9] +) * (. [A-Za-z] {2,}) $ "; @Override public void initialize (ValidEmail constraintAnnotation) {} @Override public boolean isValid (String email, ConstraintValidatorContext context) {return (validateEmail (email)); } privat boolsk validateEmail (streng e-mail) {mønster = Mønster.kompil (EMAIL_PATTERN); matcher = mønster. matcher (e-mail); returner matcher.matches (); }}

Lad os nu brug den nye kommentar på vores UserDto implementering:

@ValidEmail @NotNull @NotEmpty privat streng-mail;

5.3. Brug af brugerdefineret validering til bekræftelse af adgangskode

Vi har også brug for en brugerdefineret kommentar og validator for at sikre, at adgangskode og matchingPassword felter matcher:

Eksempel 5.3.1. - Den brugerdefinerede kommentar til validering af adgangskodebekræftelse

@Target ({TYPE, ANNOTATION_TYPE}) @Retention (RUNTIME) @Constraint (validatedBy = PasswordMatchesValidator.class) @Documented public @interface PasswordMatches {Strengmeddelelse () standard "Adgangskoder stemmer ikke overens"; Klasse [] grupper () standard {}; Klasse [] nyttelast () standard {}; }

Bemærk, at @Mål kommentar indikerer, at dette er en TYPE annotering på niveau. Dette er fordi vi har brug for det hele UserDto modsætter sig at udføre valideringen.

Den brugerdefinerede validator, der kaldes til ved denne kommentar, vises nedenfor:

Eksempel 5.3.2. Det PasswordMatchesValidator Custom Validator

offentlig klasse PasswordMatchesValidator implementerer ConstraintValidator {@Override public void initialize (PasswordMatches constraintAnnotation) {} @Override public boolean isValid (Object obj, ConstraintValidatorContext context) {UserDto user = (UserDto) obj; returner user.getPassword (). er lig med (user.getMatchingPassword ()); }}

Nu, den @PasswordMatches annotering skal anvendes på vores UserDto objekt:

@PasswordMatches offentlig klasse UserDto {...}

Alle brugerdefinerede valideringer evalueres naturligvis sammen med alle standardkommentarer, når hele valideringsprocessen kører.

5.4. Kontroller, at kontoen ikke allerede findes

Den fjerde kontrol, vi implementerer, er at bekræfte, at e-mail konto findes ikke allerede i databasen.

Dette udføres, når formularen er valideret, og det gøres ved hjælp af UserService implementering.

Eksempel 5.4.1. - Controlleren createUserAccount Metode Opkald til UserService Object

@PostMapping ("/ bruger / registrering") offentlig ModelAndView registerUserAccount (@ModelAttribute ("bruger") @Valid UserDto userDto, HttpServletRequest anmodning, Fejlfejl) {prøv {Brugerregistreret = userService.registerNewUserAccount (userDto); } fange (UserAlreadyExistException uaeEx) {mav.addObject ("meddelelse", "Der findes allerede en konto for det brugernavn / e-mail."); returnere mav; } // resten af ​​implementeringen} 

Eksempel 5.4.2. - BrugerService Kontroller for duplikerede e-mails

@Service offentlig klasse UserService implementerer IUserService {@Autowired private UserRepository repository; @Transactional @ Override public User registerNewUserAccount (UserDto userDto) kaster UserAlreadyExistException {if (emailExist (userDto.getEmail ())) {throw new UserAlreadyExistException ("Der er en konto med den e-mail-adresse:" + userDto.getEmail ()); } ... // resten af ​​registreringshandlingen} privat boolsk emailExist (streng-e-mail) {return userRepository.findByEmail (email)! = null; }}

UserService er afhængig af UserRepository klasse for at kontrollere, om en bruger med en given e-mail-adresse allerede findes i databasen.

Nu - den faktiske implementering af UserRepository i persistenslaget er ikke relevant for den aktuelle artikel. En hurtig måde er selvfølgelig at bruge Spring Data til at generere lageret.

6. Vedvarende data og efterbehandling af formularbehandling

Endelig - lad os implementere registreringslogikken i vores controller-lag:

Eksempel 6.1.1. - Det RegisterAccount Metode i controlleren

@PostMapping ("/ bruger / registrering") offentlig ModelAndView registerUserAccount (@ModelAttribute ("bruger") @Valid UserDto userDto, HttpServletRequest anmodning, Fejlfejl) {prøv {Brugerregistreret = userService.registerNewUserAccount (userDto); } fange (UserAlreadyExistException uaeEx) {mav.addObject ("meddelelse", "Der findes allerede en konto for dette brugernavn / e-mail."); returnere mav; } returner ny ModelAndView ("successRegister", "user", userDto); } 

Ting at bemærke i ovenstående kode:

  1. Styringen vender tilbage a ModelAndView objekt, der er den bekvemme klasse til afsendelse af modeldata (bruger) bundet til udsigten.
  2. Den registeransvarlige omdirigerer til registreringsformularen, hvis der er fejl, der er indstillet på valideringstidspunktet.

7.Det UserService - Registrer operation

Lad os afslutte implementeringen af ​​registreringsoperationen i UserService:

Eksempel 7.1. Det IUserService Interface

offentlig grænseflade IUserService {User registerNewUserAccount (UserDto userDto) kaster UserAlreadyExistException; }

Eksempel 7.2. - Det UserService Klasse

@Service offentlig klasse UserService implementerer IUserService {@Autowired private UserRepository repository; @Transactional @ Override public User registerNewUserAccount (UserDto userDto) throw UserAlreadyExistException {if (emailExists (userDto.getEmail ())) {throw new UserAlreadyExistException ("Der er en konto med den e-mail-adresse: + userDto.getEmail ());} Bruger bruger = ny bruger (); user.setFirstName (userDto.getFirstName ()); user.setLastName (userDto.getLastName ()); user.setPassword (userDto.getPassword ()); user.setEmail (userDto.getEmail ()) ; user.setRoles (Arrays.asList ("ROLE_USER")); returner repository.save (bruger);} private boolske emailExists (streng e-mail) {return userRepository.findByEmail (email)! = null;}}

8. Indlæser brugeroplysninger til sikkerhedslogin

I vores tidligere artikel brugte login hårdt kodede legitimationsoplysninger. Lad os ændre det og Brug de nyregistrerede brugeroplysninger og legitimationsoplysninger. Vi implementerer en brugerdefineret UserDetailsService for at kontrollere legitimationsoplysningerne for login fra persistenslaget.

8.1. Den brugerdefinerede UserDetailsService

Lad os starte med den tilpassede brugerinformation service implementering:

@Service @Transactional public class MyUserDetailsService implementerer UserDetailsService {@Autowired privat UserRepository userRepository; // offentlige UserDetails loadUserByUsername (String email) kaster UsernameNotFoundException {User user = userRepository.findByEmail (email); if (user == null) {throw new UsernameNotFoundException ("Ingen bruger fundet med brugernavn:" + email); } boolsk aktiveret = sandt; boolsk accountNonExpired = sand; boolske legitimationsoplysningerNonExpired = true; boolsk accountNonLocked = sand; returner nyt org.springframework.security.core.userdetails.User (user.getEmail (), user.getPassword (). toLowerCase (), aktiveret, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities (user.getRoles ())); } privat statisk liste getAuthorities (listeroller) {Liste autoriteter = ny ArrayList (); for (String rolle: roller) {autoriteter.add (ny SimpleGrantedAuthority (rolle)); } returneringsmyndigheder }}

8.2. Aktivér den nye godkendelsesudbyder

For at aktivere den nye brugertjeneste i Spring Security-konfigurationen - skal vi blot tilføje en reference til UserDetailsService inde i godkendelses-manager element og tilføj UserDetailsService bønne:

Eksempel 8.2. - Godkendelsesadministratoren og UserDetailsService

Eller via Java-konfiguration:

@Autowired privat MyUserDetailsService userDetailsService; @ Override beskyttet ugyldig konfiguration (AuthenticationManagerBuilder auth) kaster Undtagelse {auth.userDetailsService (userDetailsService); }

9. Konklusion

Og vi er færdige - en komplet og næsten produktionsklar registreringsproces implementeret med Spring Security og Spring MVC. Dernæst skal vi diskutere processen med at aktivere den nyregistrerede konto ved at bekræfte e-mail fra den nye bruger.

Implementeringen af ​​dette Spring Security REST-tutorial kan findes i GitHub-projektet - dette er et Eclipse-baseret projekt, så det skal være let at importere og køre som det er.

Næste » Registrering - Aktiver en ny konto via e-mail « Tidligere forårssikkerhedsregistreringsvejledning