我们正在创建一个grails aplication,我们希望用户使用他们的Active Directory凭据登录。此外,我们希望为此应用程序的业务所有者提供控制谁可以访问某些链接(操作)的能力。因此,我们在grails应用程序中使用以下插件:
因为我们希望授权业务用户在必要时动态创建具有特定权限(操作)的自定义角色,我们认为最好的Spring安全配置是基于Requestmap数据库的方法
到目前为止,我们完成了以下工作:
问题/问题
spring-security-core插件创建了以下表格:
这些是支持角色创建的表,即角色的URL分配。但是,Person_Authoritity表作为约定名称意味着它是PERSON和AUTHORITY(ROLE)之间的多对多关系,因为一个人可能有多个角色。我的问题是我没有Person,因为该人已存在于Active Directory(外部源)中,并且未在应用程序中创建。
有没有办法让经过身份验证的用户成为PERSON? Spring安全解决方案需要Person行或对象,但您更喜欢引用它。
我也在这里发布了这个问题:
谢谢,
答案 0 :(得分:6)
因此,您需要将AD用户实际映射到Person。
以下是src / groovy中需要的3个类。显然可以根据需要修改它们:
package yourpackagename
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser
import org.springframework.security.core.GrantedAuthority
class CustomUserDetails extends GrailsUser{
final String firstName
final String lastName
CustomUserDetails(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked,
Collection<GrantedAuthority> authorities,
long id, String firstName, String lastName) {
super(username, password, enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, authorities, id)
this.firstName = firstName
this.lastName = lastName
}
}
package yourpackagenamehere
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
class CustomUserDetailsService implements GrailsUserDetailsService {
/**
* Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least one role, so
* we give a user with no granted roles this one which gets past that restriction but
* doesn't grant anything.
*/
static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
UserDetails loadUserByUsername(String username, boolean loadRoles)
throws UsernameNotFoundException {
return loadUserByUsername(username)
}
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User.withTransaction { status ->
User user = User.findByUsername(username)
if (!user) throw new UsernameNotFoundException('User not found', username)
def authorities = user.authorities.collect {new GrantedAuthorityImpl(it.authority)}
return new CustomUserDetails(user.username, user.password, user.enabled,
!user.accountExpired, !user.passwordExpired,
!user.accountLocked, authorities ?: NO_ROLES, user.id,
user.firstName, user.lastName)
} as UserDetails
}
}
package yourpackagenamehere
import groovy.sql.Sql
import org.springframework.ldap.core.DirContextAdapter
import org.springframework.ldap.core.DirContextOperations
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.security.core.GrantedAuthority
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.authentication.DisabledException
class CustomUserDetailsContextMapper implements UserDetailsContextMapper {
private static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
def dataSource
@Override
public CustomUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authority) {
username = username.toLowerCase()
User user = User.findByUsername(username)
String firstName = ctx.originalAttrs.attrs['givenname'].values[0]
String lastName = ctx.originalAttrs.attrs['sn'].values[0]
def roles
User.withTransaction {
if(!user){
user = new User(username: username, enabled: true, firstName: firstName, lastName: lastName)
user.save(flush: true)
}
else {
user = User.findByUsername(username)
user.firstName = firstName
user.lastName = lastName
user.save(flush: true)
}
roles = user.getAuthorities()
}
if ( !user.enabled )
throw new DisabledException("User is disabled", username)
def authorities = roles.collect { new GrantedAuthorityImpl(it.authority) }
authorities.addAll(authority)
def userDetails = new CustomUserDetails(username, user.password, user.enabled, false, false, false, authorities, user.id, user.firstName, user.lastName)
return userDetails
}
@Override
public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {
}
}
在spring / resources.groovy中配置:
import yourpackagenamehere.CustomUserDetailsService
import yourpackagenamehere.CustomUserDetailsContextMapper
beans = {
userDetailsService(CustomUserDetailsService)
ldapUserDetailsMapper(CustomUserDetailsContextMapper) {
dataSource = ref("dataSource")
}
}
在Config.groovy下,这是我的设置:
grails.plugins.springsecurity.ldap.context.managerDn = 'CN=username,OU=People,DC=foo,DC=com'
grails.plugins.springsecurity.ldap.context.managerPassword = 'password'
grails.plugins.springsecurity.ldap.context.server = 'ldap://foo.com:389/'
grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException = true
grails.plugins.springsecurity.ldap.search.base = 'ou=People,dc=foo,dc=com'
grails.plugins.springsecurity.ldap.search.filter="sAMAccountName={0}"
grails.plugins.springsecurity.ldap.search.searchSubtree = true
grails.plugins.springsecurity.ldap.auth.hideUserNotFoundExceptions = false
grails.plugins.springsecurity.ldap.search.attributesToReturn = null
grails.plugins.springsecurity.providerNames = ['ldapAuthProvider', 'anonymousAuthenticationProvider']
grails.plugins.springsecurity.ldap.mapper.userDetailsClass = 'CustomUserDetails'
grails.plugins.springsecurity.ldap.authorities.retrieveGroupRoles = true
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = true
grails.plugins.springsecurity.ldap.authorities.groupSearchBase ='dc=foo,dc=com'
grails.plugins.springsecurity.ldap.authorities.groupSearchFilter = 'member={0}'