Backtracking all our previous tutorial you will notice we always had our user definition with password placed in our database. Not every time this will be the case and frequently we will have to integrate our application with LDAP. In this tutorial we will integrate our earlier application with Apache Directory Services. If you don’t know how to configure Apache DS then take look at Configuring Apache DS.
In this post we are not implementing anything for remember-me service which we did earlier. Let’s get started with code changes to cater to LDAP Spring Security Integration for both Authentication and Authorization
First We will clean up jsfspring-sec-bean-config.xml
as we don’t need anything related to database.
jsfspring-sec-bean-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <beans:bean id="navigator" name="navigator" class="com.mumz.jsfspringsec.beans.Navigator" scope="session"> <beans:property name="businessModel" ref="businessModel"></beans:property> </beans:bean> <beans:bean id="loginBean" name="loginBean" class="com.mumz.jsfspringsec.beans.LoginBean" scope="prototype"> <beans:property name="authenticationManager" ref="authenticationManager"></beans:property> </beans:bean> <beans:bean id="securityBean" class="com.mumz.jsfspringsec.beans.SecurityHolderBean" scope="session"> </beans:bean> <beans:bean id="businessModel" class="com.mumz.jsfspringsec.business.model.BusinessModel" scope="prototype"></beans:bean> <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" /> <beans:property name="url" value="jdbc:mysql://localhost:3306/jsf-spring-security" /> <beans:property name="username" value="root" /> <beans:property name="password" value="root" /> </beans:bean> </beans:beans>
Notice that configuration is very simple and all information related to custom database and user details service have been removed.
Second we will update jsfspring-sec-security-config.xml
. We will define LdapAuthenticationProvider which uses BindAuthenticator. This won’t work where LDAP is secured and logging to LDAP is disabled. In those cases use PasswordComparisonAuthenticator.
jsfspring-sec-security-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <sec:http auto-config="true" use-expressions="true"> <sec:intercept-url pattern="/pages/secure/**" access="hasRole('ROLE_USER')" /> <sec:intercept-url pattern="/pages/unsecure/**" access="permitAll"/> <sec:intercept-url pattern="/pages/common/**" access="permitAll"/> <sec:intercept-url pattern="/**" access="permitAll"/> <sec:form-login login-page="/pages/common/login.jsf"/> <sec:logout invalidate-session="true" delete-cookies="JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE" logout-success-url="/pages/common/login.jsf"></sec:logout> </sec:http> <sec:authentication-manager alias="authenticationManager"> <sec:authentication-provider ref="ldapAuthProvider"></sec:authentication-provider> </sec:authentication-manager> <beans:bean id="ldapContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource"> <beans:constructor-arg value="ldap://localhost:12389/o=mycompany"/> <beans:property name="userDn" value="uid=admin,ou=system"/> <beans:property name="password" value="secret"/> </beans:bean> <beans:bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider"> <beans:constructor-arg> <beans:bean class="org.springframework.security.ldap.authentication.BindAuthenticator"> <beans:constructor-arg ref="ldapContextSource"/> <beans:property name="userDnPatterns"> <beans:list> <beans:value>uid={0},ou=Users</beans:value> </beans:list> </beans:property> </beans:bean> </beans:constructor-arg> <beans:constructor-arg> <beans:bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator"> <beans:constructor-arg ref="ldapContextSource"/> <beans:constructor-arg value="ou=Groups"/> <beans:property name="groupRoleAttribute" value="cn"/> </beans:bean> </beans:constructor-arg> </beans:bean> <sec:global-method-security pre-post-annotations="enabled"/> </beans:beans>
Finally our sleek LoginBean.java
which just does the login, remember me has been removed.
LoginBean.java
package com.mumz.jsfspringsec.beans; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.RequestScoped; import javax.faces.context.FacesContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; /** * The Class LoginBean. */ @ManagedBean(name = "loginMgmtBean") @RequestScoped public class LoginBean { /** The user name. */ private String userName = null; /** The password. */ private String password = null; /** The remember me. */ private String rememberMe = null; /** The authentication manager. */ @ManagedProperty(value = "#{authenticationManager}") private AuthenticationManager authenticationManager = null; /** * Login. * * @return the string */ public String login() { try { Authentication result = null; Authentication request = new UsernamePasswordAuthenticationToken(this.getUserName(), this.getPassword()); result = authenticationManager.authenticate(request); SecurityContextHolder.getContext().setAuthentication(result); } catch (AuthenticationException e) { e.printStackTrace(); } return "Secured"; } /** * Cancel. * * @return the string */ public String cancel() { return null; } /** * Logout. * * @return the string */ public String logout() { SecurityContextHolder.clearContext(); /** * Delete Cookies */ HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext() .getResponse(); Cookie cookie = new Cookie("SPRING_SECURITY_REMEMBER_ME_COOKIE", null); cookie.setMaxAge(0); cookie.setPath(httpServletRequest.getContextPath().length() > 0 ? httpServletRequest.getContextPath() : "/"); httpServletResponse.addCookie(cookie); return "loggedout"; } /** * Gets the user name. * * @return the user name */ public String getUserName() { return userName; } /** * Sets the user name. * * @param userName * the new user name */ public void setUserName(String userName) { this.userName = userName; } /** * Gets the password. * * @return the password */ public String getPassword() { return password; } /** * Sets the password. * * @param password * the new password */ public void setPassword(String password) { this.password = password; } /** * Gets the remember me. * * @return the remember me */ public String getRememberMe() { return rememberMe; } /** * Sets the remember me. * * @param rememberMe * the new remember me */ public void setRememberMe(String rememberMe) { this.rememberMe = rememberMe; } /** * Gets the authentication manager. * * @return the authentication manager */ public AuthenticationManager getAuthenticationManager() { return authenticationManager; } /** * Sets the authentication manager. * * @param authenticationManager * the new authentication manager */ public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } }
That’s all we need for integration Spring Security and LDAP (Apache DS in this case) for both Authorization and Authentication. There is every possibility that LDAP may be used for Authentication and Authorization will be done from database, in another post we will look at one way of implementing such a solution.
References:
Boa documentacao! Parabens pelo post.
I would like create an application which authenticate against an LDAP Server an the users authorities are derived from the database.I can find a complete exemple.notes that i’am not familiar with Spring security . it will be great if you guide me or any one how have source code can share it with me.
Cool, the idea of a set of articles that somehow modifies an original source code is great. But it would be even cooler if the articles references back the and forward everything that is linked. Also, a download of the complete project for each article would be nice.