Vårsikkerhet - Roller og privilegier

1. Oversikt

Denne artikkelen fortsetter Registration with Spring Security-serien med en titt på hvordan du skal implementere riktig Roller og privilegier.

2. BrukerRoll og Privilegium

Først, la oss starte med enhetene våre. Vi har tre hovedenheter:

  • de Bruker
  • de Roll - dette representerer brukerens høye roller i systemet; hver rolle vil ha et sett med privilegier på lavt nivå
  • de Privilegium - representerer et lavt nivå, granulært privilegium / autoritet i systemet

Her er brukeren:

@Entity offentlig klasse bruker {@Id @GeneratedValue (strategi = GenerationType.AUTO) privat Lang id; privat streng fornavn; privat streng etternavn; privat streng e-post; privat strengpassord; privat boolsk aktivert; privat boolsk tokenUtløpt; @ManyToMany @JoinTable (name = "users_roles", joinColumns = @JoinColumn (name = "user_id", referencedColumnName = "id"), inverseJoinColumn = @JoinColumn (name = "role_id", referatedColumnName = "id")) private samlingsroller ; }

Som du kan se, inneholder brukeren rollene, men også noen ekstra detaljer som er nødvendige for en riktig registreringsmekanisme.

Neste - her er rollen:

@Entity offentlig klasse rolle {@Id @GeneratedValue (strategi = GenerationType.AUTO) privat Lang id; privat strengnavn; @ManyToMany (mappedBy = "roller") brukere av private samlinger; @ManyToMany @JoinTable (name = "roller_privileges ", joinColumns = @JoinColumn (name =" role_id ", referatedColumnName =" id "), inverseJoinColumn = @JoinColumn (name =" privilege_id ", referatedColumnName =" id ")) private rettigheter ; }

Og endelig privilegiet:

@Entity public class Privilege {@Id @GeneratedValue (strategi = GenerationType.AUTO) privat Lang id; privat strengnavn; @ManyToMany (mappedBy = "privilegier") private samlingsroller; }

Som du ser, vurderer vi både brukerrollen og rolleprivilegeforholdene mange-til-mange toveis.

3. Konfigurer privilegier og roller

Neste - la oss fokusere på å gjøre noe tidlig oppsett av privilegier og roller i systemet.

Vi knytter dette til oppstart av applikasjonen, og vi bruker en ApplicationListenerContextRefreshedEvent for å laste inn våre første data på serverstart:

@Komponent offentlig klasse SetupDataLoader implementerer ApplicationListener {boolean alreadySetup = false; @Autowired privat UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired private PrivilegeRepository privilegeRepository; @Autowired privat PasswordEncoder passordEncoder; @ Override @ Transactional public void onApplicationEvent (ContextRefreshedEvent event) {if (alreadySetup) return; Privilege readPrivilege = createPrivilegeIfNotFound ("READ_PRIVILEGE"); Privilege writePrivilege = createPrivilegeIfNotFound ("WRITE_PRIVILEGE"); Liste adminPrivileges = Arrays.asList (readPrivilege, writePrivilege); createRoleIfNotFound ("ROLE_ADMIN", adminPrivileges); createRoleIfNotFound ("ROLE_USER", Arrays.asList (readPrivilege)); Rolle adminRole = roleRepository.findByName ("ROLE_ADMIN"); Brukerbruker = ny bruker (); user.setFirstName ("Test"); user.setLastName ("Test"); user.setPassword (passwordEncoder.encode ("test")); user.setEmail ("[email protected]"); user.setRoles (Arrays.asList (adminRole)); user.setEnabled (true); userRepository.save (bruker); alreadySetup = true; } @Transactional Privilege createPrivilegeIfNotFound (String name) {Privilege privilege = privilegeRepository.findByName (name); hvis (privilegium == null) {privilegium = nytt privilegium (navn); privilegeRepository.save (privilegium); } returner privilegium; } @Transactional Role createRoleIfNotFound (String name, Collection privilegies) {Role role = roleRepository.findByName (name); hvis (rolle == null) {rolle = ny rolle (navn); role.setPrivileges (privilegier); roleRepository.save (rolle); } returrolle; }}

Så, hva skjer under denne enkle installasjonskoden? Ikke noe komplisert:

  • vi skaper privilegier
  • vi lager rollene og tildeler dem privilegiene
  • vi oppretter en bruker og tildeler en rolle til den

Legg merke til hvordan vi bruker en allerede oppsett flagg til avgjøre om installasjonen må kjøre eller ikke. Dette er ganske enkelt fordi, avhengig av hvor mange sammenhenger du har konfigurert i applikasjonen din - ContextRefreshedEvent kan sparkes flere ganger. Og vi vil bare at oppsettet skal utføres en gang.

To raske notater her - først om terminologi. Vi bruker Privilege - Roll vilkår her, men om våren er disse litt forskjellige. På våren blir vårt privilegium referert til som rolle, og også som en (gitt) autoritet - noe som er litt forvirrende. Ikke noe problem for implementeringen selvfølgelig, men absolutt verdt å merke seg.

For det andre - disse vårrollene (våre privilegier) trenger et prefiks; Som standard er dette prefikset “ROLE”, men det kan endres. Vi bruker ikke dette prefikset her, bare for å holde ting enkle, men husk at hvis du ikke eksplisitt endrer det, vil det være nødvendig.

4. Tilpasset UserDetailsService

Nå - la oss sjekke ut autentiseringsprosessen.

Vi kommer til å se hvordan vi kan hente brukeren innenfor vår skikk UserDetailsService, og hvordan man kartlegger det rette settet med autoriteter fra rollene og privilegiene brukeren har tildelt:

@Service ("userDetailsService") @Transactional public class MyUserDetailsService implementerer UserDetailsService {@Autowired privat UserRepository userRepository; @Autowired privat IUserService-tjeneste; @Autowired private MessageSource-meldinger; @Autowired private RoleRepository roleRepository; @ Override public UserDetails loadUserByUsername (String email) kaster UsernameNotFoundException {User user = userRepository.findByEmail (email); if (user == null) {returner ny org.springframework.security.core.userdetails.User ("", "", true, true, true, true, getAuthorities (Arrays.asList (roleRepository.findByName ("ROLE_USER")) ))); } returner ny org.springframework.security.core.userdetails.User (user.getEmail (), user.getPassword (), user.isEnabled (), true, true, true, getAuthorities (user.getRoles ())); } private Collection getAuthorities (Samlingsroller) {retur getGrantedAuthorities (getPrivileges (roller)); } privat liste getPrivileges (Samlingsroller) {List privilegier = ny ArrayList (); Listesamling = ny ArrayList (); for (Rollerolle: roller) {collection.addAll (role.getPrivileges ()); } for (Privilege item: collection) {privileges.add (item.getName ()); } returnere privilegier; } privat liste getGrantedAuthorities (Liste privilegier) {Liste myndigheter = ny ArrayList (); for (String privilege: privileges) {autoriteter.add (ny SimpleGrantedAuthority (privilegium)); } returmyndigheter; }}

Det interessante å følge her er hvordan privilegiene (og rollene) blir kartlagt til GrantedAuthority-enheter.

Denne kartleggingen gjør hele sikkerhetskonfigurasjonen svært fleksibel og kraftig - du kan blande og matche roller og privilegier så detaljerte som nødvendig, og til slutt blir de riktig kartlagt til myndighetene og returnert tilbake til rammeverket.

5. Bruker Registrering

Til slutt - la oss ta en titt på registrering for en ny bruker.

Vi har sett hvordan oppsett går til å lage brukeren og tildeler roller (og privilegier) til det - la oss nå se på hvordan dette må gjøres under registrering av en ny bruker:

@ Override public User registerNewUserAccount (UserDto accountDto) kaster EmailExistsException {if (emailExist (accountDto.getEmail ())) {throw new EmailExistsException ("Det er en konto med den e-postadressen:" + accountDto.getEmail ()); } Brukerbruker = ny bruker (); user.setFirstName (accountDto.getFirstName ()); user.setLastName (accountDto.getLastName ()); user.setPassword (passwordEncoder.encode (accountDto.getPassword ())); user.setEmail (accountDto.getEmail ()); user.setRoles (Arrays.asList (roleRepository.findByName ("ROLE_USER"))); returner repository.save (bruker); }

I denne enkle implementeringen antar vi at en standardbruker blir registrert, så ROLE_USER rolle er tildelt den.

Selvfølgelig kan mer komplisert logikk enkelt implementeres på samme måte - enten ved å ha flere, hardkodede registreringsmetoder, eller ved å la klienten sende typen bruker som blir registrert.

6. Konklusjon

I denne opplæringen illustrerte vi hvordan du implementerer roller og privilegier med JPA, for et Spring Security-støttet system.

De full gjennomføring av denne veiledningen for registrering med vårsikkerhet finner du i GitHub-prosjektet - dette er et Maven-basert prosjekt, så det skal være enkelt å importere og kjøre som det er.


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