-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enhance ldap user service to support filtering users by group
- Loading branch information
Showing
6 changed files
with
535 additions
and
19 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
apollo-portal/src/main/config/application-ldap-apacheds-sample.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
spring: | ||
ldap: | ||
base: "dc=example,dc=com" | ||
username: "uid=admin,ou=system" # 配置管理员账号,用于搜索、匹配用户 | ||
password: "password" | ||
searchFilter: "(uid={0})" # 用户过滤器,登录的时候用这个过滤器来搜索用户 | ||
urls: | ||
- "ldap://localhost:10389" | ||
|
||
ldap: | ||
mapping: # 配置 ldap 属性 | ||
objectClass: "inetOrgPerson" # ldap 用户 objectClass 配置 | ||
loginId: "uid" # ldap 用户惟一 id,用来作为登录的 id | ||
rdnKey: "cn" # ldap rdn key | ||
userDisplayName: "displayName" # ldap 用户名,用来作为显示名 | ||
email: "mail" # ldap 邮箱属性 | ||
group: # 配置ldap group | ||
objectClass: "groupOfNames" # 配置groupClassName | ||
groupBase: "ou=group" # group search base | ||
groupSearch: "(&(cn=apollo-admins)(&(member=*)))" # group filter | ||
groupMembership: "member" # group memberShip eg. member or memberUid |
20 changes: 20 additions & 0 deletions
20
apollo-portal/src/main/config/application-ldap-openldap-sample.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
spring: | ||
ldap: | ||
base: "dc=example,dc=com" | ||
username: "cn=Manager,dc=example,dc=com" # 配置管理员账号,用于搜索、匹配用户 | ||
password: "password" | ||
searchFilter: "(uid={0})" # 用户过滤器,登录的时候用这个过滤器来搜索用户 | ||
urls: | ||
- "ldap://localhost:389" | ||
|
||
ldap: | ||
mapping: # 配置 ldap 属性 | ||
objectClass: "inetOrgPerson" # ldap 用户 objectClass 配置 | ||
loginId: "uid" # ldap 用户惟一 id,用来作为登录的 id | ||
rdnKey: "uid" # ldap rdn key | ||
userDisplayName: "displayName" # ldap 用户名,用来作为显示名 | ||
email: "mail" # ldap 邮箱属性 | ||
group: # 配置ldap group | ||
groupBase: "ou=Group" # group search base | ||
groupSearch: "(&(cn=apollo-admins))" # group filter | ||
groupMembership: "memberUid" # group memberShip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
...c/main/java/com/ctrip/framework/apollo/portal/spi/configuration/LdapExtendProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
* Copyright (c) 2019 www.ceair.com Inc. All rights reserved. | ||
*/ | ||
|
||
package com.ctrip.framework.apollo.portal.spi.configuration; | ||
|
||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
/** | ||
* the LdapExtendProperties description. | ||
* | ||
* @author wuzishu | ||
*/ | ||
@ConfigurationProperties(prefix = "ldap") | ||
public class LdapExtendProperties { | ||
|
||
private LdapMappingProperties mapping; | ||
private LdapGroupProperties group; | ||
|
||
public LdapMappingProperties getMapping() { | ||
return mapping; | ||
} | ||
|
||
public void setMapping(LdapMappingProperties mapping) { | ||
this.mapping = mapping; | ||
} | ||
|
||
public LdapGroupProperties getGroup() { | ||
return group; | ||
} | ||
|
||
public void setGroup(LdapGroupProperties group) { | ||
this.group = group; | ||
} | ||
} | ||
class LdapMappingProperties{ | ||
|
||
/** | ||
* user ldap objectClass | ||
*/ | ||
private String objectClass; | ||
|
||
/** | ||
* user login Id | ||
*/ | ||
private String loginId; | ||
|
||
/** | ||
* user rdn key | ||
*/ | ||
private String rdnKey; | ||
|
||
/** | ||
* user display name | ||
*/ | ||
private String userDisplayName; | ||
|
||
/** | ||
*/ | ||
private String email; | ||
|
||
public String getObjectClass() { | ||
return objectClass; | ||
} | ||
|
||
public void setObjectClass(String objectClass) { | ||
this.objectClass = objectClass; | ||
} | ||
|
||
public String getLoginId() { | ||
return loginId; | ||
} | ||
|
||
public void setLoginId(String loginId) { | ||
this.loginId = loginId; | ||
} | ||
|
||
public String getRdnKey() { | ||
return rdnKey; | ||
} | ||
|
||
public void setRdnKey(String rdnKey) { | ||
this.rdnKey = rdnKey; | ||
} | ||
|
||
public String getUserDisplayName() { | ||
return userDisplayName; | ||
} | ||
|
||
public void setUserDisplayName(String userDisplayName) { | ||
this.userDisplayName = userDisplayName; | ||
} | ||
|
||
public String getEmail() { | ||
return email; | ||
} | ||
|
||
public void setEmail(String email) { | ||
this.email = email; | ||
} | ||
} | ||
class LdapGroupProperties{ | ||
|
||
/** | ||
* group search base | ||
*/ | ||
private String groupBase; | ||
|
||
/** | ||
* group search filter | ||
*/ | ||
private String groupSearch; | ||
|
||
/** | ||
* group membership prop | ||
*/ | ||
private String groupMembership; | ||
|
||
public String getGroupBase() { | ||
return groupBase; | ||
} | ||
|
||
public void setGroupBase(String groupBase) { | ||
this.groupBase = groupBase; | ||
} | ||
|
||
public String getGroupSearch() { | ||
return groupSearch; | ||
} | ||
|
||
public void setGroupSearch(String groupSearch) { | ||
this.groupSearch = groupSearch; | ||
} | ||
|
||
public String getGroupMembership() { | ||
return groupMembership; | ||
} | ||
|
||
public void setGroupMembership(String groupMembership) { | ||
this.groupMembership = groupMembership; | ||
} | ||
} |
100 changes: 100 additions & 0 deletions
100
...src/main/java/com/ctrip/framework/apollo/portal/spi/ldap/FilterLdapByGroupUserSearch.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
|
||
|
||
package com.ctrip.framework.apollo.portal.spi.ldap; | ||
|
||
import static org.springframework.ldap.query.LdapQueryBuilder.query; | ||
|
||
import javax.naming.Name; | ||
import javax.naming.directory.SearchControls; | ||
import javax.naming.ldap.LdapName; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.ldap.core.DirContextAdapter; | ||
import org.springframework.ldap.core.DirContextOperations; | ||
import org.springframework.ldap.core.support.BaseLdapPathContextSource; | ||
import org.springframework.ldap.support.LdapUtils; | ||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | ||
import org.springframework.security.ldap.SpringSecurityLdapTemplate; | ||
import org.springframework.security.ldap.search.FilterBasedLdapUserSearch; | ||
|
||
/** | ||
* the FilterLdapByGroupUserSearch description. | ||
* | ||
* @author wuzishu | ||
*/ | ||
public class FilterLdapByGroupUserSearch extends FilterBasedLdapUserSearch { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(FilterLdapByGroupUserSearch.class); | ||
private static final String MEMBER_UID_ATTR_NAME = "memberUid"; | ||
private String searchBase; | ||
private String groupBase; | ||
private String groupSearch; | ||
private String rdnKey; | ||
private String groupMembershipAttrName; | ||
private String loginIdAttrName; | ||
|
||
private final SearchControls searchControls = new SearchControls(); | ||
|
||
private BaseLdapPathContextSource contextSource; | ||
|
||
|
||
public FilterLdapByGroupUserSearch(String searchBase, String searchFilter, | ||
String groupBase, BaseLdapPathContextSource contextSource, String groupSearch, | ||
String rdnKey, String groupMembershipAttrName, String loginIdAttrName) { | ||
super(searchBase, searchFilter, contextSource); | ||
this.searchBase = searchBase; | ||
this.groupBase = groupBase; | ||
this.groupSearch = groupSearch; | ||
this.contextSource = contextSource; | ||
this.rdnKey = rdnKey; | ||
this.groupMembershipAttrName = groupMembershipAttrName; | ||
this.loginIdAttrName = loginIdAttrName; | ||
} | ||
|
||
private Name searchUserById(String userId) { | ||
SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(this.contextSource); | ||
template.setSearchControls(searchControls); | ||
return template.searchForObject(query().where(this.loginIdAttrName).is(userId), | ||
ctx -> ((DirContextAdapter) ctx).getDn()); | ||
} | ||
|
||
|
||
@Override | ||
public DirContextOperations searchForUser(String username) { | ||
if (logger.isDebugEnabled()) { | ||
logger.debug("Searching for user '" + username + "', with user search " + this); | ||
} | ||
SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(this.contextSource); | ||
template.setSearchControls(searchControls); | ||
return template | ||
.searchForObject(groupBase, groupSearch, ctx -> { | ||
if (!MEMBER_UID_ATTR_NAME.equals(groupMembershipAttrName)) { | ||
String[] members = ((DirContextAdapter) ctx) | ||
.getStringAttributes(groupMembershipAttrName); | ||
for (String item : members) { | ||
LdapName memberDn = LdapUtils.newLdapName(item); | ||
LdapName memberRdn = LdapUtils | ||
.removeFirst(memberDn, LdapUtils.newLdapName(searchBase)); | ||
String rdnValue = LdapUtils.getValue(memberRdn, rdnKey).toString(); | ||
if (rdnValue.equalsIgnoreCase(username)) { | ||
return new DirContextAdapter(memberRdn.toString()); | ||
} | ||
} | ||
throw new UsernameNotFoundException("User " + username + " not found in directory."); | ||
} else { | ||
String[] memberUids = ((DirContextAdapter) ctx) | ||
.getStringAttributes(groupMembershipAttrName); | ||
for (String memberUid : memberUids) { | ||
if (memberUid.equalsIgnoreCase(username)) { | ||
Name name = searchUserById(memberUid); | ||
LdapName ldapName = LdapUtils.newLdapName(name); | ||
LdapName ldapRdn = LdapUtils | ||
.removeFirst(ldapName, LdapUtils.newLdapName(searchBase)); | ||
return new DirContextAdapter(ldapRdn); | ||
} | ||
} | ||
} | ||
throw new UsernameNotFoundException("User " + username + " not found in directory."); | ||
}); | ||
} | ||
} |
Oops, something went wrong.