我终于能够编写一个独立的java,我能够连接到LDAP并获取用户名,并且能够进行身份验证(使用密码)。但是当我在Spring LDAP中尝试相同的url和其他细节时,我收到了错误。没有得到我在Spring LDAP中缺少的东西。请帮忙???
LDAPService.java(独立)
public class LDAPService {
private final static int ACCOUNT_DISABLED = 2;
private static String[] ldapUrls = null;
private static String adminId = null;
private static String adminPassword = null;
private static SearchControls searchCtls = null;
private static String defaultGroup = null;
private static LDAPService ldapService;
private static String searchBase = null;
private int domainIndex;
private int domainCount;
public static LDAPService getInstance() {
if(ldapService == null ) ldapService = new LDAPService();
return ldapService;
}
public LDAPService() {
super();
String ldapUrl = "ldap://mycompany-ldap-tdu.lb.xyz.dm.company.com:389/OU=Engine,OU=PQR%20Global,DC=am,DC=mds,DC=pqr,DC=com";
ldapUrls = StringUtils.split(ldapUrl, ";");
adminId = "CN=APP-XYZ-GRP,OU=Non-Person,OU=Users,OU=QWE,OU=Engine,OU=PQR Global,DC=am,DC=mds,DC=pqr,DC=com";
adminPassword = "admpasswd";
defaultGroup = "85";
searchBase = "";
searchCtls = new SearchControls();
String attrTemp = "distinguishedName,userPassword,memberOf,pwdLastSet,accountExpires,userAccountControl,givenName,sn";
String returnedAtts[]= null;
if(null != attrTemp){
StringTokenizer st = new StringTokenizer(attrTemp,",");
int size = st.countTokens();
returnedAtts = new String[size];
int counter = 0;
while(st.hasMoreElements()){
returnedAtts[counter++] = st.nextToken();
}
}
int scope = 2;
searchCtls.setReturningAttributes(returnedAtts);
searchCtls.setSearchScope(scope);
//Start with a random domain controller to balance load.
Random randomGenerator = new Random();
domainIndex = randomGenerator.nextInt(ldapUrls.length);
domainCount = 0;
}
private Hashtable<String,String> getEnvironment(String userId, String password) {
Hashtable<String,String> envDC = new Hashtable<String,String>();
envDC.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
envDC.put(Context.SECURITY_AUTHENTICATION,"simple");
envDC.put(Context.PROVIDER_URL, ldapUrls[domainIndex]);
envDC.put(Context.SECURITY_PRINCIPAL,userId);
envDC.put(Context.SECURITY_CREDENTIALS,password);
return envDC;
}
public List<UserSecurityGroupId> authenticate(String userId,String password)throws Exception{
List<UserSecurityGroupId> groups = null;
String distinguishedName = null;
String memberOf = null;
Long pwdLastSet = null;
Long accountExpires = null;
Hashtable<String,String> envGC = getEnvironment(adminId, adminPassword);
String searchFilter = "(&(cn="+ userId + ")(objectClass=user))";
try{
LdapContext ctxGC = new InitialLdapContext(envGC,null);
//search LDAP Server using search Filter.
NamingEnumeration answer = ctxGC.search(searchBase, searchFilter, searchCtls);
if (answer.hasMoreElements()) {
SearchResult result = (SearchResult)answer.next();
Attributes attrs = result.getAttributes();
// get all attributes if the user exists
if (attrs != null) {
//Check if the User Account has been disabled
//This is identified by the returned values binary place holder for the decimal value 2 being a 1
if(null != attrs.get("useraccountcontrol")){
int userAccountControl = NumberUtils.toInt(attrs.get("useraccountcontrol")
.toString().replaceAll("userAccountControl: ", ""), ACCOUNT_DISABLED);
if((userAccountControl & ACCOUNT_DISABLED) == ACCOUNT_DISABLED){
return null;
}
}
//memberOf attribute retrieves the groups to which user belongs.
//only retrieve group memberships if password is provided
if(null != attrs.get("memberOf") && (null != password) && (password.trim().length() > 0)){
memberOf = attrs.get("memberOf").toString();
}
groups = getListOfGroups(memberOf, userId);
//pwdLastSet retrieves the time when password was last set.
if(null != attrs.get("pwdLastSet")){
pwdLastSet = new Long(attrs.get("pwdLastSet").get().toString());
}
//accountExpires retrieves the time when account will expire.
if(null != attrs.get("accountExpires")){
accountExpires = new Long(attrs.get("accountExpires").get().toString());
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(1601, 0, 1, 0, 0);
accountExpires = accountExpires / 10000 + calendar.getTime().getTime();
}
//distinguished name retrieves the distinguished name for the user.
if(null != attrs.get("distinguishedName")){
distinguishedName = attrs.get("distinguishedName").get().toString();
}
}
}else{
// if no attributes retrieved then user does not exist.
throw new LoginException(LoginStatus.USER_NOT_EXIST.toString());
}
ctxGC.close();
// verify if account is already expired.
if ( (null != accountExpires) && (accountExpires.longValue() > 0)) {
long today = System.currentTimeMillis();
long expireDay = accountExpires.longValue();
if ( expireDay < today ) {
throw new LoginException(LoginStatus.PASSWORD_EXPIRED.toString());
}
}
} catch (NamingException e) {
System.out.println("Naming Exception occurred");
if(checkNextDomainController())
authenticate(userId, password);
else
throw new LoginException(LoginStatus.AUTHENTICATION_ERROR.toString());
}
if(null != distinguishedName){
// verify the username and password if password is provided
if((null != password) && (password.trim().length() > 0)){
try {
Hashtable envDC = getEnvironment(distinguishedName,password);
DirContext ctx = new InitialDirContext(envDC);
ctx.close();
return groups;
}catch (CommunicationException comEx){
System.out.println("Communication Exception occurred");
if(checkNextDomainController())
return authenticate(userId, password);
else
throw new LoginException(LoginStatus.AUTHENTICATION_ERROR.toString());
}catch (AuthenticationException authEx){
authEx.printStackTrace();
System.out.println("Authentication Exception occurred");
throw new LoginException(LoginStatus.PASSWORD_INCORRECT.toString());
}catch (NamingException nameEx){
System.out.println("Naming Exception occurred");
if(checkNextDomainController())
return authenticate(userId, password);
else
throw new LoginException(LoginStatus.AUTHENTICATION_ERROR.toString());
}
}else{
return groups;
}
}else{
throw new LoginException(LoginStatus.USER_NOT_EXIST.toString());
}
}
private List<UserSecurityGroupId> getListOfGroups(String memberOf, String userId) {
List<UserSecurityGroupId> userScrityGrpList = new ArrayList<UserSecurityGroupId>();
String[] userSecurityGroupFilter = {"APP-XYZ"};
if(null != memberOf){
while(memberOf.indexOf("CN=") > 0){
memberOf = memberOf.substring(memberOf.indexOf("CN=")+3);
String tmp = memberOf.substring(0,memberOf.indexOf(','));
if(StringUtils.startsWithAny(tmp, userSecurityGroupFilter )) {
UserSecurityGroupId groupId = new UserSecurityGroupId(userId, tmp);
userScrityGrpList.add(groupId);
}
}
}
UserSecurityGroupId group = new UserSecurityGroupId(userId, defaultGroup);
if(!userScrityGrpList.contains(group)){
userScrityGrpList.add(group);
}
return userScrityGrpList;
}
/**
* This utility will return Associate Name from Active Directory corresponding to given user id.
* @param userId
* @return Associate Name
*/
public String getAssociateName(String userId) {
Hashtable<String,String> envGC = getEnvironment(adminId, adminPassword);
String searchFilter = "(&(cn="+ userId + ")(objectClass=user))";
String associateName = "";
try{
LdapContext ctxGC = new InitialLdapContext(envGC,null);
//search LDAP Server using search Filter.
NamingEnumeration answer = ctxGC.search(searchBase, searchFilter, searchCtls);
if (answer.hasMoreElements()) {
SearchResult result = (SearchResult)answer.next();
Attributes attrs = result.getAttributes();
// get all attributes if the user exists
if (attrs != null) {
//givenName attribute retrieves Given Name.
if(null != attrs.get("givenName") ){
associateName = associateName + attrs.get("givenName").get().toString() + " ";
}
//sn retrieves the Surname.
if(null != attrs.get("sn")){
associateName += attrs.get("sn").get().toString();
}
System.out.println(attrs.get("userPassword"));
}
}
ctxGC.close();
} catch (NamingException e) {
System.out.println("Naming Exception occurred while retrieving associate name");
}
return associateName;
}
public static void main(String[] a) {
LDAPService s = new LDAPService();
try {
System.out.println(s.getAssociateName("12345"));
//System.out.println(s.authenticate("12345", "password123"));
}catch(Exception e) {
e.printStackTrace();
}
}
}
WebSecurityConfiguration.java(Spring类)
@Configurable
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
try {
auth.ldapAuthentication()
.contextSource().url("ldap://mycompany-ldap-tdu.lb.xyz.dm.company.com:389/OU=Engine,OU=PQR%20Global,DC=am,DC=mds,DC=pqr,DC=com")
.managerDn("CN=APP-XYZ-GRP,OU=Non-Person,OU=Users,OU=QWE,OU=Engine,OU=PQR Global,DC=am,DC=mds,DC=pqr,DC=com")
.managerPassword("admpasswd")
.and()
.userSearchBase("")
.groupSearchBase("")
.userSearchFilter("(&(cn={0})(objectClass=user))")
.groupSearchFilter("(member=userGroup)");
}catch(Exception e) {
e.printStackTrace();
}
}
错误:
o.s.security.web.FilterChainProxy : /account/login at position 7 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
o.s.security.web.FilterChainProxy : /account/login at position 8 of 14 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'user'
o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
o.s.s.l.a.LdapAuthenticationProvider : Processing authentication request for user: user
o.s.s.l.s.FilterBasedLdapUserSearch : Searching for user 'user', with user search [ searchFilter: '(&(cn={0})(objectClass=user))', searchBase: '', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
.s.a.DefaultAuthenticationEventPublisher : No event was found for the exception org.springframework.security.authentication.InternalAuthenticationServiceException
o.s.s.w.a.www.BasicAuthenticationFilter : Authentication request for failed: org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:
'DC=am,DC=mds,DC=pqr,DC=com'
]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - 0000208D: NameErr: DSID-0310020A, problem 2001 (NO_OBJECT), data 0, best match of:
'DC=am,DC=mds,DC=pqr,DC=com'
]; remaining name '/'
Trying to match using RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]
s.w.a.DelegatingAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint@1dd945b2
w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed