Spring Security - Roller og privilegier

1. Oversigt

Denne artikel fortsætter serien med registrering med forårssikkerhed med et kig på, hvordan man korrekt implementerer Roller og privilegier.

2. BrugerRolle og Privilegium

Lad os først starte med vores enheder. Vi har tre hovedenheder:

  • det Bruger
  • det Rolle - dette repræsenterer brugerens roller på højt niveau i systemet; hver rolle har et sæt privilegier på lavt niveau
  • det Privilegium - repræsenterer et lavt niveau, granuleret privilegium / autoritet i systemet

Her er brugeren:

@Entity offentlig klasse bruger {@Id @GeneratedValue (strategi = GenerationType.AUTO) privat Lang id; privat streng fornavn; privat streng efternavn; privat streng e-mail; privat strengadgangskode; privat boolsk aktiveret privat boolsk tokenUdløbet; @ManyToMany @JoinTable (name = "users_roles", joinColumns = @JoinColumn (name = "user_id", referencedColumnName = "id"), inverseJoinColumn = @JoinColumn (name = "role_id", referencedColumnName = "id")) private indsamlingsroller ; }

Som du kan se, indeholder brugeren rollerne, men også et par yderligere detaljer, der er nødvendige for en korrekt registreringsmekanisme.

Næste - her er rollen:

@Entity offentlig klasse Rolle {@Id @GeneratedValue (strategi = GenerationType.AUTO) privat Lang id; privat strengnavn; @ManyToMany (mappedBy = "roller") private Collection-brugere; @ManyToMany @JoinTable (name = "roller_privileges ", joinColumns = @JoinColumn (name =" role_id ", referencedColumnName =" id "), inverseJoinColumn = @JoinColumn (name =" privilege_id ", referencedColumnName =" id ")) private rettigheder til samling ; }

Og endelig privilegiet:

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

Som du kan se, overvejer vi både brugerrollen samt forholdet mellem rolleprivilegier mange-til-mange tovejs.

3. Opsæt privilegier og roller

Dernæst - lad os fokusere på at udføre nogle tidlige opsætninger af privilegier og roller i systemet.

Vi binder dette til opstart af applikationen, og vi bruger en ApplicationListenerContextRefreshedEvent at indlæse vores oprindelige data på serverstart:

@Komponent offentlig klasse SetupDataLoader implementerer ApplicationListener {boolean alreadySetup = false; @Autowired privat UserRepository userRepository; @Autowired privat RoleRepository roleRepository; @Autowired privat PrivilegeRepository privilegeRepository; @Autowired privat PasswordEncoder passwordEncoder; @ 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"); Brugerbruger = ny bruger (); 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 (bruger); alreadySetup = sandt; } @Transactional Privilege createPrivilegeIfNotFound (String name) {Privilege privilege = privilegeRepository.findByName (name); hvis (privilegium == null) {privilegium = nyt privilegium (navn); privilegeRepository.save (privilegium); } returret } @Transactional Role createRoleIfNotFound (String name, Collection privileges) {Role role = roleRepository.findByName (name); hvis (rolle == null) {rolle = ny rolle (navn); role.setPrivileges (privilegier); roleRepository.save (rolle); } returrolle }}

Så hvad sker der under denne enkle installationskode? Intet kompliceret:

  • vi skaber privilegier
  • vi opretter rollerne og tildeler dem privilegierne
  • vi opretter en bruger og tildeler den en rolle

Bemærk hvordan vi bruger en allerede opsætning flag til afgøre, om opsætningen skal køre eller ej. Dette skyldes ganske enkelt, afhængigt af hvor mange sammenhænge du har konfigureret i din applikation - ContextRefreshedEvent kan fyres flere gange. Og vi vil kun have opsætningen udført en gang.

To hurtige noter her - først om terminologi. Vi bruger Privilege - Rolle vilkår her, men om foråret er disse lidt forskellige. I foråret betegnes vores privilegium som rolle og også som en (bevilget) myndighed - hvilket er lidt forvirrende. Ikke et problem for implementeringen selvfølgelig, men absolut værd at bemærke.

For det andet - disse forårsroller (vores privilegier) har brug for et præfiks; Præfikset er som standard “ROLE”, men det kan ændres. Vi bruger ikke dette præfiks her, bare for at holde tingene enkle, men husk at hvis du ikke eksplicit ændrer det, vil det være nødvendigt.

4. Brugerdefineret UserDetailsService

Lad os nu kontrollere godkendelsesprocessen.

Vi skal se, hvordan man kan hente brugeren inden for vores brugerdefinerede UserDetailsService, og hvordan man kortlægger det rigtige sæt autoriteter ud fra de roller og privilegier, som brugeren har tildelt:

@Service ("userDetailsService") @Transactional public class MyUserDetailsService implementerer UserDetailsService {@Autowired privat UserRepository userRepository; @Autowired privat IUserService-tjeneste; @Autowired private MessageSource beskeder; @Autowired privat RoleRepository roleRepository; @ Override offentlige 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 nyt org.springframework.security.core.userdetails.User (user.getEmail (), user.getPassword (), user.isEnabled (), true, true, true, getAuthorities (user.getRoles ())); } privat samling getAuthorities (indsamlingsroller) {retur getGrantedAuthorities (getPrivileges (roller)); } privat liste getPrivileges (Samlingsroller) {List privilegier = ny ArrayList (); Listesamling = ny ArrayList (); for (Rolle rolle: roller) {collection.addAll (role.getPrivileges ()); } for (Privilege item: collection) {privileges.add (item.getName ()); } returnere privilegier } privat liste getGrantedAuthorities (listeprivilegier) {Liste autoriteter = ny ArrayList (); for (String privilegium: privileges) {autoriteter.add (ny SimpleGrantedAuthority (privilegium)); } returneringsmyndigheder }}

Det interessante at følge her er, hvordan privilegierne (og rollerne) kortlægges til GrantedAuthority-enheder.

Denne kortlægning udgør hele sikkerhedskonfigurationen meget fleksibel og kraftfuld - du kan blande og matche roller og privilegier så detaljerede som nødvendigt, og i sidste ende kortlægges de korrekt til myndighederne og returneres tilbage til rammen.

5. Bruger Registrering

Endelig - lad os se på registrering for en ny bruger.

Vi har set, hvordan opsætningen går til at oprette brugeren og tildeler roller (og privilegier) til den - lad os nu se på, hvordan dette skal gøres under registrering af en ny bruger:

@ Override offentligt brugerregisterNyBrugerAccount (UserDto-kontoDto) kaster EmailExistsException {if (emailExist (accountDto.getEmail ())) {throw new EmailExistsException ("Der er en konto med den e-mail-adresse:" + accountDto.getEmail ()); } Brugerbruger = ny bruger (); 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 (bruger); }

I denne enkle implementering antager vi, at en standardbruger bliver registreret, så ROLE_USER rolle tildeles den.

Naturligvis kan mere kompleks logik let implementeres på samme måde - enten ved at have flere, hardkodede registreringsmetoder eller ved at lade klienten sende den type bruger, der bliver registreret.

6. Konklusion

I denne vejledning illustrerede vi, hvordan du implementerer roller og privilegier med JPA til et Spring Security-støttet system.

Det fuld implementering af denne registrering med Spring Security-vejledning kan findes i GitHub-projektet - dette er et Maven-baseret projekt, så det skal være let at importere og køre som det er.


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