如何将LDAP用户与Spring Security在Grails中创建的PERSON表集成在一起? [英] How to integrate an LDAP user with the PERSON table created by Spring Security in Grails?
问题描述
我们正在创建一个grails应用程序,我们希望用户使用其Active Directory凭据登录。此外,我们希望赋予此应用程序的业主拥有控制访问某些链接(操作)的权限的能力。因此,我们在我们的grails应用程序中使用了以下插件:
$ b
- Spring Security Core
- Spring Security LDAP
- Spring Security UI
因为我们希望授权业务用户创建我们认为最好的Spring Security Configuration是基于Request Map数据库的方法
到目前为止,我们已经完成了如下工作:
- 我们可以成功地对Active Directory进行身份验证。
- 我们还可以通过spring-security-ui插件的UI界面为不同的角色(ROLE_XXX)创建不同的请求映射。
spring-security-core插件创建了以下表: 这些是支持创建角色的表格,将URL分配给角色。然而,作为约定名称的Person_Authoritity表意味着它是PERSON和AUTHORITY(ROLE)之间的多对多关系,因为一个人可能具有多个角色。我的问题是我没有Person,因为这个人已经存在于Active Directory(外部源)中,并且它没有在应用程序中创建。
有没有办法让认证用户成为PERSON?弹簧安全解决方案需要Person行或对象,但是您更愿意引用它。
我也在这里发布了这个问题:
感谢,
因此,您需要将AD用户映射到Person。
以下是您在src / groovy中需要的3个类。显然可以根据需要修改它们:
package yourpackagename
import org.codehaus.groovy.grails.plugins .springsecurity.GrailsUser
import org.springframework.security.core.GrantedAuthority
$ b 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> authority,
long id,String firstName ,String lastName){
super(用户名,密码,启用,accountNonExpired,
credentialsNonExpired,accountNonLocked,权限,id)
this.firstName = firstName
this。 lastName = last名称
}
}
包yourpackagenamehere
导入org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService
导入组织。 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
类CustomUserDetailsService实现了GrailsUserDetailsService {
$ b $ / **
*一些Spring Security类(例如RoleHierarchyVoter)期望至少有一个角色,所以
*我们给予一个没有授予角色的用户,这个角色超过了这个限制,但是
*没有授予任何东西。
* /
static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
$ b $ UserDetails loadUserByUsername(String username,boolean loadRoles)
throws UsernameNotFoundException {
return loadUserByUsername(username)
}
$ b $ 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)}
返回新的CustomUserDetails(user.username,user.password,user.enabled,
!user.accountExpired,!user.passwordExpired ,
!user.accountLocked,authority?:NO_ROLES,user.id,
user.firstName,user.lastName)
}作为UserDetails
}
}
package yourpackagenamehere here
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.springframew ork.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
类CustomUserDetailsContextMapper实现UserDetailsContextMapper {
private static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
def dataSource
$ b $ @Override
public CustomUserDetails mapUserFromContext(DirContextOperations ctx,String username,Collection< GrantedAuthority>权限){
用户名= username.toLowerCase()
用户用户= User.findByUsername(用户名)
字符串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)
抛出新的DisabledException(用户被禁用,用户名)
def authorities = roles.collect {new GrantedAuthorityImpl(it.authority)}
authorities.addAll(authority)
def userDetails = new CustomUserDetails(username,user .password,user.enabled,false,false,false,user.id,user.firstName,user.lastName)
return userDetails
}
@Override
public void mapUserToContext(UserDetails arg0,DirContextAdapter arg1){
}
}
在spring / resources.groovy的配置下:
导入yourpackagenamehere.CustomUserDetailsService
导入yourpackagenamehere。 CustomUserDetailsContextMapper
beans = {
userDetailsService(CustomUserDetailsService)
ldapUserDetailsMapper(CustomUserDetailsContextMapper){
dataSource = ref(dataSource)
}
}
在Config.groovy下,这里是我的设置:
grails.plugins.springsecurity.ldap.context.managerDn ='CN = username,OU =人员,DC = foo,DC = com'
grails.plugins .springsecurity.ldap.context.managerPassword ='密码'
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.autho rities.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}'
We are creating a grails aplication where we want the user to log in using their Active Directory credentials. Additionally, we want to give the business owner of this application the ability to control who has access to certain links (actions). Because of this we are using the following plugins in our grails application:
- Spring Security Core
- Spring Security LDAP
- Spring Security UI
Because we want to empower the business user to create customized roles with certain permissions(actions) on the fly when necessary, we think that the best Spring Security Configuration is the Requestmap database based approach
So far we have accomplished as follows:
- We are being able to authenticate against Active Directory successfully.
- We have also been able to create different Request Mappings for different roles (ROLE_XXX) through the UI interface of the spring-security-ui plugin
Problems/Questions
The spring-security-core plugin created the following tables:
- PERSON
- AUTHORITY
- PERSON_AUTHORITY
- REQUESTMAP
These are the tables that support the creation of Roles, the assignment of URLs to roles. However, the Person_Authoritity table as the convention name implies it's a many to many relationship between a PERSON and an AUTHORITY (ROLE) since a person can potentially have more than one role. My problem is that I do not have a Person because the person already exists in Active Directory (an external source) and it was not created in the application.
Is there a way to make the authenticated user to be the PERSON ? The spring security solution requires that Person row or object however you prefer to refer to it.
I have also posted the question here:
Thanks,
So you need to essentially map the AD user to a Person.
Here are the 3 classes you need in src/groovy. Obviously modify them as needed:
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) {
}
}
Under configuration in spring/resources.groovy :
import yourpackagenamehere.CustomUserDetailsService
import yourpackagenamehere.CustomUserDetailsContextMapper
beans = {
userDetailsService(CustomUserDetailsService)
ldapUserDetailsMapper(CustomUserDetailsContextMapper) {
dataSource = ref("dataSource")
}
}
Under Config.groovy, here are my settings:
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}'
这篇关于如何将LDAP用户与Spring Security在Grails中创建的PERSON表集成在一起?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!