If you want to control the access to a web application and make it secure within a Spring environment, a good approach is to apply the Microsoft Active Directory (LDAP) authentication.
However, when I tried to apply this approach I found it was not easy to put all the elements together. The online documentation for Spring Security was not clear enough to my understanding and the synchronisation of dependencies not properly explained; I found a good reference on this ComDynamics article, but again with some missing parts.
After hours of research and test I realised that the Spring Security framework allows high flexibility and lets you customise
the way you authenticate and secure your web applications. Once I managed to get it all working I decided to write this new entry on my blog to have everything in one place.
Include your dependencies
The next Spring Security 3.1.0.RELEASE dependencies are required in your pom.xml file to perform the security checks:
- spring-security-core
- spring-security-config
- spring-security-web
- spring-security-ldap
ActiveDirectoryLdapAuthenticationProvider is the core class in Spring Security 3.1 to allow the integration with LDAP, and one of my first problems was that the versions of Spring Security 3.1 I was using did not include this class in their classpaths, so make sure the version of your dependencies includes it (version 3.1.0.RELEASE does).
Apart from these dependencies, you will also need to include the next one:
- spring-ldap-core (version 1.3.1.RELEASE worked for me)
Configure your files within the WEB-INF folder
In this case, the security configuration is specified in the security.xml file, under WEB-INF, so in order for the security context to be loaded, your web.xml file should look as shown next:
The application configuration needs to also provide the security filter chain, by specifying the set of URLs that will be processed by the security filter. In this case, all the URLs will require to be secured, so the web.xml file should include the following:
Configure your security context
As stated above, the security context in this example will be detailed in the security.xml file (under WEB-INF), which will look like shown in the following snippet:
As stated above, the security context in this example will be detailed in the security.xml file (under WEB-INF), which will look like shown in the following snippet:
It is important to describe some of the elements in the security context:
Configure your login page - ldapActiveDirectoryAuthProvider: This bean will use the core Spring Security 3.1 class to integrate with LDAP: ActiveDirectoryLdapAuthenticationProvider, which accepts a list of parameters as shown in the example
- Constructor arguments: ${ldap.domain} and ${ldap.url} represent your Active Directory configuration, that is the domain to which the users belong and the url to connect to the LDAP server
- authoritiesMapper: This bean is needed to filter the roles within the LDAP groups; it will check whether the users belong to certain LDAP groups or not. The bean uses the customised class com.targetapp.webapp.security.ActiveDirectoryGrantedAuthoritiesMapper, which is explained below
- security:http: This section specifies your login/logout policy, as well as your security zones:
- form-login, where you detail the login page, the login processing url and the redirections in case of success or failure in the authentication
- logout, redirection on sucessful logout
- itercept-url, which allows you to create as many security zones as you need in your web application, specifying the roles that have permission to access each of the security zones; for simplicity in this example there is only one role, ROLE_ADMIN, that has access to all the sites in the web application, but your LDAP configuration could have different roles with access to different zones in your web application
Make sure that your form uses the login-processing-url specified in the security.xml file, in this case "/j_spring_security_check".
Configure your role mappings
In order to match the nomenclature used in your security context (security.xml) you need to create the customised mapper class that will be used to implement the authoritiesMapper bean previously declared in the security context.
This will imply the creation of two classes:
com.targetapp.webapp.security.SecurityContextAuthority
This class implements the Spring interface GrantedAuthority; it provides the set of the roles used in the security context, that will be mapped by the next class
com.targetapp.webapp.security.ActiveDirectoryGrantedAuthoritiesMapper
This class implements the Spring interface GrantedAuthoritiesMapper; the method mapAuthorities
gets as argument the set of authorities in the LDAP nomenclature which is mapped to the set of authorities defined in the previous class (in the security context nomenclature); the method will provide the ActiveDirectoryLdapAuthenticationProvider class with the list of roles available for the user that is trying to login
At this point you should have all your configuration ready to provide your web application with Active Directory security.
I have created a demo of this but my execution never goes in the ActiveDirectoryGrantedAuthoritiesMapper class at all.
ReplyDeletehelp me ....
Many many Thanx
Hi Ravinder, thanks very much for reading this post.
ReplyDeleteCould you please give a bit more of information?
Do you have any logs?
Does your execution through any exceptions?
However, one thing that is worth double checking is the version of Spring Security you are using and if it contains the next class in the right path: org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider
Please let me know.
Hi Julio,
ReplyDeleteThanks for the reply.
I am using 3.1.0 RELEASE and i have verified the path you provided. It's same.
When i try to login with correct/incorrect credentials it simple redirect me to error page. Even there is no error in log as well.
Please guide.
Thanks.
Can you set your logging level to DEBUG mode?
DeleteThis should generate more information about the logging process and it should point at the reason why you are being redirected to the error page, or at least you should be able to view the classes that are being used for the login.
which ldap server should I download ? Plz guide
ReplyDeleteI load as roles or user permissions yourself the database?
ReplyDeleteHi,
ReplyDeleteI am trying thid example and keep getting this error when trying to login:
java.lang.ClassCastException: org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider cannot be cast to .ActiveDirectoryAuthentication
Anyone know can help on this?
Thanks.
Could you please give more details?
DeleteHave you checked if you are using the right Spring versions?
Hi Julio,
DeleteThanks. I managed to set it up already. But I am facing with this issue even though I have enter the correct credential.
2013-07-19 10:29:04,619 [http-bio-8080-exec-4] INFO org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider - Active Directory authentication failed: Supplied password was invalid
BadCredentialsException: org.springframework.security.authentication.BadCredentialsException: Bad credentials
Hello,
DeleteGood to know that you solved the previous issue.
Did you use the right case-sensitivity?
Please let me know.
Hi Julio,
DeleteThank you for your reply. What do u mean by right case-senitivity?
I'm having the EXACT SAME issue as WenJun. I know it's partially working though because if I enter a nonsense username or incorrect password, I get a log message saying username not found or password not valid. If I use a correct username and password, it gives me the BadCredentailsException
DeleteAlso, I tried all uppercase and all lowercase on my username but it gives the same BadCredentialsException either way. I'm assuming it accepts either because it didn't give me a "username not found" message.
DeleteHello again,
DeleteAfter analysing the issues with WenJun, we found out that the occurred because of the LDAP domain definition (ldap.domain) of the "ldapActiveDirectoryAuthProvider" bean; it has to be done with a fomat like "abc.com" instead of "dc=abc,dc=com".
Best regards,
Julio
I believe the bug I'm seeing may be a bug in ActiveDirectoryLdapAuthenticationProvider. I found the following forum post on the spring boards:
Deletehttp://forum.springsource.org/showthread.php?134991-Active-Directory-authentication-in-Spring-3-1
And I created a JIRA issue for it here since one didn't seem to exist:
https://jira.springsource.org/browse/SEC-2224
Agreed with Julio. Thank once again for the help render. :)
ReplyDeleteRegards,
WenJun
hi Julio Diego Barrado Fernández
ReplyDeletei am facing the issue as below
java.lang.ClassNotFoundException: org.springframework.aop.config.AbstractInterceptorDrivenBeanDefinitionDecorator
i checked that class is present in classpath.. then why this error is coming.plss help me
Hi Julio
ReplyDeleteI'm having the same problem: Bad Credentials
Hola Julio, exelente post!, te hago una consulta, como puedo hacer para reeplazar los argumentos:
ReplyDeletela idea es reemplazarlos por datos obtenidos de un properties.
Muchas gracias,. un saludo.
perdon Julio, los argumentos:
ReplyDelete${ldap.domain}
${ldap.url}
Hola Sergio,
DeleteCreo que lo que necesitas hacer es incluir el fichero properties en tu "applicationContext-resources.xml", por ejemplo, si añades un bean como el siguiente:
< b ean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
< p roperty name="ignoreUnresolvablePlaceholders" value="true"/>
< p roperty name="locations">
< l ist>
< v alue>classpath:jdbc.properties< / v alue>
< v alue>classpath:mail.properties< / v alue>
< v alue>classpath:application.properties< / v alue>
< / l ist>
< / p roperty>
< / b ean>
Una vez hecho esto, puedes añadir los valores para tus parámetros en el "application.properties".
Ya me dices si te ha servido mi sugerencia o no.
Un saludo,
Julio
Hola Julio, exactamente!!, asi lo hice, cree un aplication.properties con:
Deleteldap.domain=WIN-R747K5VOO12
ldap.url=ldap://WIN-R747K5VOO12:389
ahora si al poner un usuario/pass en mi pagina Login.jsp se me conecta bien a mi maquina con un AD corriendo (WIN-R747K5VOO12), PERO, tengo el mismo problema que los muchachos de mas arriba, bad credencials!!, si quieres te pego los archivos de configuracion para ver si puedes dilucidar cual es mi problema!.
Venga Julio!, me ha sido de mucha utilidad tu post!.
Un abrazo!!