2015-12-09 14 views
8

Skonfigurowałem moje wiosenne bezpieczeństwo do pracy z grupami.Grails Spring Security Rola i grupa

użyłem tego skrypcie do tworzenia klas domeny:

grails s2-quickstart com.yourapp User Role --groupClassName=RoleGroup 

Przypuszczałem, że użytkownik może mieć wiele grup, gdzie grupa może mieć wiele ról

To właśnie wygenerowany metoda wygląda w klasa użytkownika:

Set<RoleGroup> getAuthorities() { 
    UserRoleGroup.findAllByUser(this).collect { it.roleGroup } 
} 

Ale teraz widać, że skrypt stworzony również klasę o nazwie UserRole który jest związek pomiędzy Użytkownikiem a rola. Zatem użytkownik może mieć również wiele ról bezpośrednio?

Próbowałem go i jest zapisany w bazie danych. I zmodyfikowane metody takiego:

def getAuthorities() { 
    def authorities = UserRoleGroup.findAllByUser(this).collect { it.roleGroup } 

    authorities.addAll(UserRole.findAllByUser(this).collect { it.role }) 
    return authorities 
} 

Teraz, kiedy utworzyć wpis w bazie danych Użytkownika < -> Rola asocjacji. Nie mogę się już zalogować. Dostaję domyślny komunikat przez ochronę wiosenną, mówiąc w zasadzie, że nie znaleziono żadnych danych uwierzytelniających.

Po ręcznym usunięciu wpisu mogę zalogować się ponownie. Myślę, że dzieje się tak dlatego, że metoda zwraca tylko obiekty RoleGroup.

Moje pytania są następujące:

a) można także przypisać role bezpośrednio kiedy mam skonfigurowane grupy

b) jeżeli nie, to dlaczego jest skrypt tworzenia tej klasy

c) jeżeli tak, jak mogę to zrobić?

Odpowiedz

2

Nie sądzę, że można się było spodziewać przypisania Role bezpośrednio do User, gdy używasz Groups.

Przypisz Group użytkownikowi i Role do Group.

myślę, że przedstawiony struktura kod może być przydatna, gdy „obniżenia” aplikacja

używać tylko User i Roles, bez zerwania aktualny zestaw reguł.

1

To tylko moja opinia: skrypt utworzył UserRole, ponieważ jest to po prostu klasa optymalizacji, na przykład jeśli otrzymasz rolę z db i spróbujesz znaleźć jakąś hibernację użytkownika, który powinien otrzymać wszystkich użytkowników z serwera proxy. To tylko klasa optymalizacji. Jeśli chcesz mieć jedną rolę na użytkownika, możesz ustawić ją w UserRole.create() Dodaj ograniczenie i powinno działać. Mam nadzieję, że mnie zrozumiesz i zrozumiałem, że masz rację. Miłego dnia

0

nieco stary, ale może przyjść w ręku, aby ktokolwiek inny próbuje grupy:

W klasie użytkownika:

Set<RoleGroup> getAuthorities() { 
    (UserRoleGroup.findAllByUser(this) as List<UserRoleGroup>)*.roleGroup as Set<RoleGroup> 
} 



Set<Role> getRoles() { 
    (UserRoleGroup?.findAllByUser(this)?.roleGroup?.authorities.collect{it}?.flatten() ?: oldRoles) as Set<Role> 
} 

List<String> getRoleNames() { 
     (UserRoleGroup?.findAllByUser(this)?.roleGroup?.collect{it.authorities.authority}?.flatten()?: oldRoles.authority) as List<String> 
} 

//Above will look up from userRoleGroup roleGroup.authorities = UserRole below 
Set<Role> getOldRoles() { 
    (UserRole.findAllByUser(this) as List<Role>)*.role as Set<Role> 
} 

byłem za pomocą ról choć grupy była włączona i uwierzytelnianie przeciwko starych oldRoles metoda:

import grails.plugin.springsecurity.userdetails.GormUserDetailsService 
import grails.transaction.Transactional 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken 
import org.springframework.security.core.Authentication 
import org.springframework.security.core.GrantedAuthority 
import org.springframework.security.core.authority.SimpleGrantedAuthority 
import org.springframework.security.core.context.SecurityContextHolder 
import org.springframework.security.core.userdetails.UserDetails 
import org.springframework.security.core.userdetails.UsernameNotFoundException 

class MySpringSecurityAuthenticator extends GormUserDetailsService{ 

    UserDetails loadUserByUsername(String username, boolean loadRoles) 
      throws UsernameNotFoundException { 
     return loadUserByUsername(username) 
    } 

    @Transactional 
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
     //enable login with either username or password 
     User user = User.find { 
      username == username || attributes.emailAddress == username || userCode == username 
     } 
     //if (!user) throw new UsernameNotFoundException('User not found', username) 
     if (!user) throw new UsernameNotFoundException('User not found') 
     return loadUserByUsername(user) 
    } 
    @Transactional 
    UserDetails loadUserByUsername(User user) throws UsernameNotFoundException { 
     if (!user) throw new UsernameNotFoundException('User not found') 
     //UserDetails.withNewSession { 
//getAuthorities(user.oldRoles) 
      UserDetails userDetails = new org.springframework.security.core.userdetails.User(user.username, user.password, 
        user.enabled, !user.accountExpired, !user.passwordExpired, !user.accountLocked,getAuthoritiesFromGroup(user.authorities)) 
      Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()) 
      SecurityContextHolder.getContext().setAuthentication(authentication) 
      return userDetails 
     //} 
    } 

    public static List<GrantedAuthority> getAuthoritiesFromGroup(Set<RoleGroup> roles) { 
     List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>() 
     roles?.each { role -> 
      println "-- role = ${role} vs ${role.getClass()}" 
      authorities.add(new SimpleGrantedAuthority(role.name)) 
     } 
     return authorities 
    } 
    public static List<GrantedAuthority> getAuthorities(Set<Role> roles) { 
     List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>() 
     roles?.each { role -> 
      println "-- role = ${role} vs ${role.getClass()}" 
      authorities.add(new SimpleGrantedAuthority(role.authority)) 
     } 
     return authorities 
    } 
} 

iw moim wiosna/resources.groovy:

userDetailsService(MySpringSecurityAuthenticator){ 
    grailsApplication = ref('grailsApplication') 
} 

Co powyżej robił do tej pory jechałem z powrotem do ról użytkowników i dodając je do obsługi uwierzytelniania poprzez .. getAuthorities (user.oldRoles)

Mam teraz zmienił powyższy sposób, aby przeczytać w nazwach grup poprzez getAuthoritiesFromGroup (user.authorities)

To po prostu analizuje nazwy grup, które na stronie (skutek) wersji używam musi również obejmować ROLE_GROUPNAME słowo

Więc teraz, jeśli utworzyć

@Transactional 
def grantPermission(User user, String role='ROLE_ADMIN', String group='ROLE_SUPERGROUP') { 
    def adminRole = Role.findByAuthority(role) 
    if (!adminRole) { 
     adminRole = new Role(authority: role).save(flush: true) 

    } 
    UserRole.create user, adminRole, true 

    def adminRoleGroup = RoleGroup.findByName(group) 
    if (!adminRoleGroup) { 
     adminRoleGroup = new RoleGroup(name: group).save(flush: true) 
    } 
    def adminRoleGroupRole = RoleGroupRole.findByRole(adminRole) 
    if (!adminRoleGroupRole) { 
     adminRoleGroupRole = new RoleGroupRole(role: adminRole, roleGroup: adminRoleGroup).save(flush: true) 
    } 
    def alreadyDone = UserRoleGroup.findByUserAndRoleGroup(user,adminRoleGroup) 
    if (!alreadyDone) { 
     new UserRoleGroup(user: user, roleGroup: adminRoleGroup).save(flush: true) 
    } 
} 

Oczekuję uwierzytelnić przed nazwami Grupy i nie ról użytkowników tak w skrócie musiałem zmienić swój kontroler

@Secured("hasAnyRole('ROLE_SUPERGROUP')") 

nadzieję, że to ma sens, powinna być prosta do naśladowania po prostu potrzeba czasu, aby dostać twoja głowa dookoła to wszystko ..

W tym momencie wciąż bawię się i nie użyłbym jako konkretnej odpowiedzi, ponieważ jestem w pewnym sensie hacking to, aby powiedzieć, dodaj moje grupy jako moje władze i jeśli chcę to zrobić może dodać kolejny hak, aby przejść dalej przez każdą z tych grup i każdą z rzeczywistych ról w nim - nie wiedząc, co to spowoduje - w tej chwili

Chcę go zmienić na requestMaps i przenieść go do db, więc wiele do zmiany i zdecyduje, czy powinienem wrócić, czy użyć grup, które znam W ten sposób mogę skonfigurować mniej nazwisk niż kontrolerów i polegać na nazwach grup ..

czy inaczej jej pod maską tego wszystkiego i daje jasny obraz na kilka lat, ale może się przydać dla innych

Aktualizuj Więc zdecydowałem się pójść z: ,getAuthorities(user.roles)

Gdzie Set<Role> getRoles() { metoda wewnątrz powyższego kawałka kodu

Powód jest dość prosty:

results?.each { 
      it.user=User.get(it.id) 
      println "-- \n${it.id}:${it.user.roles} \n${it.id}:${it.user.oldRoles}" 


7:[Role(authority:ROLE_ADMIN), Role(authority:ROLE_ADMINAHHA)] 
7:[Role(authority:ROLE_ADMIN)] 

Jak widać dodałem nowego użytkownika używając getOldRoles widzę tylko 1 rolę na getRoles I dostać 2 role .. Dodałem użytkownika z 2 rolami ..

Teraz to będzie teraz parsować wszystkie role użytkowników i dodać je do List<GrantedAuthority> uwierzytelnianie nadal będzie za pośrednictwem rzeczywistych nazw ROLE generowanych jak poprzednio.

Oznacza to tylko, kiedy wyłączyć grupę od użytkownika to powinno zatrzymać ładowanie że zezwolenie dla tego użytkownika ..

to właśnie model powinien robić

Powiązane problemy