Reputation: 4805
I'm trying to access my project using LDAP. It prompts for username and password successfully, but put the correct credentials in it causes the prompt popup again (it seems the credentials are wrong, but they aren't).
Here's my security-context.xml:
<?xml version="1.0" encoding="utf-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<ldap-server url="ldap://${ldap.host}:${ldap.port}/${ldap.root}" manager-dn="${ldap.manager.dn}" manager-password="${ldap.manager.password}" />
<authentication-manager>
<ldap-authentication-provider group-search-base="${ldap.group.search.base}" user-search-filter="(uid={0})" user-search-base="${ldap.user.search.base}" />
</authentication-manager>
<http use-expressions="true">
<intercept-url pattern="/**" />
<http-basic />
</http>
</beans:beans>
Passwords are stored as {MD5}hash... And I'm using jsr 250 api.
EDIT:
@TobyHobson this results in org.xml.sax.SAXParseException; lineNumber: 14; columnNumber: 38; cvc-complex-type.2.4.a: Invalid content was found starting with element 'password-encoder'. One of '{"http://www.springframework.org/schema/security":password-compare}' is expected.
EDIT2:
@TobyHobson putting password-compare
around password-encoder
seems to compile, but it still rejects my correct credentials.
EDIT3: Here are necessary logs:
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'sessionFactory'
DEBUG: org.springframework.security.web.FilterChainProxy - /licenses/index.html at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession returned null object for SPRING_SECURITY_CONTEXT
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@397af435. A new one will be created.
DEBUG: org.springframework.security.web.FilterChainProxy - /licenses/index.html at position 2 of 8 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
DEBUG: org.springframework.security.web.authentication.www.BasicAuthenticationFilter - Basic Authentication Authorization header found for user 'demo_admin'
DEBUG: org.springframework.security.authentication.ProviderManager - Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
DEBUG: org.springframework.security.ldap.authentication.LdapAuthenticationProvider - Processing authentication request for user: demo_admin
DEBUG: org.springframework.security.ldap.search.FilterBasedLdapUserSearch - Searching for user 'demo_admin', with user search [ searchFilter: '(uid={0})', searchBase: 'ou=people', scope: subtree, searchTimeLimit: 0, derefLinkFlag: false ]
DEBUG: org.springframework.security.ldap.SpringSecurityLdapTemplate - Searching for entry under DN 'dc=ubuntu,dc=local', base = 'ou=people', filter = '(uid={0})'
DEBUG: org.springframework.security.ldap.SpringSecurityLdapTemplate - Found DN: uid=demo_admin,ou=people
DEBUG: org.springframework.security.ldap.authentication.PasswordComparisonAuthenticator - Performing LDAP compare of password attribute 'userPassword' for user 'uid=demo_admin,ou=people'
DEBUG: org.springframework.security.web.authentication.www.BasicAuthenticationFilter - Authentication request for failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
EDIT4: I guess it has something to do with jsr 250 api and groups/roles. Here's my ldif:
dn: ou=people,dc=ubuntu,dc=local
objectClass: organizationalUnit
ou: people
dn: uid=demo_admin,ou=people,dc=ubuntu,dc=local
userPassword: {MD5}fe01ce2a7fbac8fafaed7c982a04e229
objectClass: posixAccount
objectClass: account
homeDirectory: null
uid: demo_admin
uidNumber: 1001
gidNumber: 1000
cn: Demo Admin
dn: uid=demo_manager,ou=people,dc=ubuntu,dc=local
userPassword: {MD5}fe01ce2a7fbac8fafaed7c982a04e229
objectClass: posixAccount
objectClass: account
homeDirectory: null
uid: demo_manager
uidNumber: 2001
gidNumber: 2000
cn: Demo Manager
dn: uid=demo_viewer,ou=people,dc=ubuntu,dc=local
userPassword: {MD5}fe01ce2a7fbac8fafaed7c982a04e229
objectClass: posixAccount
objectClass: account
homeDirectory: null
uid: demo_viewer
uidNumber: 3001
gidNumber: 3000
cn: Demo Viewer
dn: ou=groups,dc=ubuntu,dc=local
objectClass: organizationalUnit
ou: groups
dn: cn=Admins,ou=groups,dc=ubuntu,dc=local
objectClass: posixGroup
cn: Admins
gidNumber: 1000
dn: cn=Managers,ou=groups,dc=ubuntu,dc=local
objectClass: posixGroup
cn: Managers
gidNumber: 2000
dn: cn=Viewers,ou=groups,dc=ubuntu,dc=local
objectClass: posixGroup
cn: Viewers
gidNumber: 3000
I used @RolesAllowed({ Role.ROLE_ADMIN, Role.ROLE_MANAGER, Role.ROLE_VIEWER })
in my controller and this is my absract role class:
public abstract class Role
{
public static final String ROLE_ADMIN = "Admins";
public static final String ROLE_MANAGER = "Managers";
public static final String ROLE_VIEWER = "Viewers";
}
Upvotes: 2
Views: 7938
Reputation: 1501
There in no need to defining hashing in spring security configuration file,the hashing technique will be handled by ldap itself. The only one thing you have to do is storing the MD5 password in ldap like this....
Attributes attrs = new BasicAttributes();
BasicAttribute ocattr = new BasicAttribute("objectclass");
ocattr.add("top");
ocattr.add("person");
ocattr.add("inetorgperson");
ocattr.add("organizationalperson");
attrs.put(ocattr);
attrs.put("sn",user.getName());
attrs.put("userPassword","{MD5}"+user.getPassword());
Upvotes: 1
Reputation: 22752
The password encoding scheme is immaterial when using bind authentication, because the password check is performed in the directory, not within Spring Security code, so Spring Security has no need to hash the password or have any knowledge of how it is stored. It will be sent as plaintext to the directory so you should use an ldaps connection if you are concerned about that.
If you were authenticating using an LDAP "compare" operation, then you would have to send an identical copy of the password field to the directory. This is error prone as it depends on the case being correct, etc. There is also no current provided support for {MD5} hashes, though there is an LdapShaPasswordEncoder
which handles {SHA} and {SSHA}.
Most likely your setup is failing for some other reason, which should be clear from a closer exmination of the debug logs and your LDAP server log.
Upvotes: 0
Reputation:
You need to add a password encoder to your authentication provider to tell Spring to hash the password before binding in LDAP. e.g.
<authentication-manager>
<ldap-authentication-provider group-search-base="${ldap.group.search.base}" user-search-filter="(uid={0})" user-search-base="${ldap.user.search.base}">
<password-encoder hash="md5"/>
</ldap-authentication-provider>
</authentication-manager>
If you use a salt you would also need to include this e.g.
<password-encoder hash="md5">
<salt-source user-property="username"/>
</password-encoder>
Upvotes: 1