grails spring安全角色和组

时间:2015-12-09 15:01:31

标签: grails spring-security

我已将弹簧安全配置为与群组配合使用。

我用这个scipt来创建域类:

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

我认为用户可以有多个组,其中一个组可以有多个角色

这是User类中生成的方法的样子:

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

但是现在我看到脚本还创建了一个名为UserRole的类,它是User和Role之间的关联。用户可以直接拥有多个角色吗?

我尝试了它并保存在数据库中。我修改了这样的方法:

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

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

现在,当我在User&lt; - &gt;中创建数据库中的条目时角色关联。我不能再登录了。我得到spring security的默认消息,基本上说没有找到凭据。

当我手动删除条目时,我可以再次登录。我认为这是因为该方法只返回RoleGroup对象。

我的问题是:

a)我可以在配置组

时直接分配角色

b)如果不是,为什么脚本会创建这个类

c)如果是,我该怎么做?

3 个答案:

答案 0 :(得分:4)

我不认为当您使用Role时,您希望将User直接分配给Groups

为用户分配Group,为Role分配Group

我认为当&#34;降级&#34;时,所呈现的代码结构可能很有用。你的应用

仅使用UserRoles,而不会违反您当前的规则。

答案 1 :(得分:1)

这只是我的意见:脚本创建UserRole,因为它只是优化类,例如,如果你从db接收角色并试图找到一些用户hibernate应该从代理接收所有用户。它只是优化类。如果您想为每个用户创建一个角色,可以在UserRole.create()中设置它 添加限制,它应该工作。希望你能理解我,我理解你。祝你有愉快的一天

答案 2 :(得分:1)

有点旧,但可能会出现在其他任何尝试过小组的人手中:

在User类中:

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>
}

即使已启用组并使用旧的oldRoles方法进行身份验证,我也一直在使用角色:

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
    }
}

在我的spring / resources.groovy:

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

上面所做的是回到用户ROLES并通过.. getAuthorities(user.oldRoles)将它们添加到身份验证处理程序

我现在更改了上面的方法,通过getAuthoritiesFromGroup(user.authorities)读取组名

这只是解析组名,作为我正在使用的版本的一面(效果)还必须包含单词ROLE_GROUPNAME

现在如果创建

@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)
    }
}

我希望对组名进行身份验证,而不是用户角色,所以总之我必须将控制器更改为

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

希望有意义的是应该直截了当地花点时间来了解所有这些......

此时我还在玩,我不会用作具体的答案,因为我有点黑客说我把我的团体添加为我的权限,如果我想我可以添加另一个钩子去进一步通过这些小组和每个实际角色 - 不确定会产生什么 - 目前

我想将它更改为requestMaps并将其移至db以便进行大量更改并决定是否应该还原或使用组我知道这样我可以在控制器上配置较少的名称并依赖于组名称。

无论哪种方式都是它的全部内容,几年后给你一个明确的想法,但可能会派上用场其他人

更新 所以我决定采用: ,getAuthorities(user.roles)

上面代码中的Set<Role> getRoles() {方法

原因很简单:

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)]

正如你所看到我使用getOldRoles添加了一个新用户我只在getRoles上看到1个角色我得到2个角色..我确实添加了2个角色的用户..

因此,现在将解析所有用户角色并将其添加到List<GrantedAuthority>,身份验证仍将通过之前生成的实际ROLE名称进行。

这只是意味着当我从用户禁用一个组时,这应该停止为该用户加载该权限..

这就是模型应该做的事情