Saturday 8 October 2011

How to: interface JasperReports Server and LDAP (1/2)

Recently I've managed at work to interface JasperReports Server 4.1 with OpenLDAP: since it's a very common problem, with very little documentation around the net (particularly regarding Jaspersoft BI Suite 4.x), I thought I'd describe here a sample configuration.
The software I used in my demo was:
  • OpenLDAP for Windows
  • LDAP Browser/Editor v. 2.8.1
  • JasperReports Server 4.1 (commercial edition)
First of all, I strongly recommend to enable the LDAP log in JasperReports Server: in order to do so, we simply add the following line in the /jasperserver-pro/WEB-INF/log4.properties:
log4j.logger.org.springframework.security.ldap=DEBUG, stdout, fileout
This way, we can monitor the LDAP activities by reading the output lines in /jasperserver-pro/WEB-INF/logs/jasperserver.log
This is the LDAP structure described in this sample configuration:

We want to add in JasperReports Server two users:
  • Tom, a normal user, under the users organization;
  • Paul, a developer, under the jobs organization
Both organizations are under the OrganizationalUnit People, which we want to add to JasperReports Server too.
In the LDAP directory we have a GroupOfNames called developer, which paul is a member of: we want to map this information as a role in JasperReports Server, and assign this new ROLE_DEVELOPER to Paul during his first login.
The first thing we want to do is enabling the ldapAuthenticationProvider: in order to do so, we have to open the file /jasperserver-pro/WEB-INF/applicationContext-security.xml, locate the AuthenticationManager bean and uncomment the ldapAuthenticationProvider reference:

<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
        <property name="providers">
            <list>
                <!-- not on by default <ref local="ldapAuthenticationProvider"/>  -->
         <ref local="ldapAuthenticationProvider"/>
                <ref bean="${bean.daoAuthenticationProvider}"/>
                <ref bean="anonymousAuthenticationProvider"/>
                <!--ref local="jaasAuthenticationProvider"/-->
            </list>
        </property>
</bean>
It's important not to comment the daoAuthenticationProvider (the one that enables the default authentication) if you want to keep using the predefined administrator users (jasperadmin and superuser). AnonymousAuthenticationProvider is necessary in order to view the login page.
Next step is setting the LDAP connection parameters: in the same file /jasperserver-pro/WEB-INF/applicationContext-security.xml, we have to locate and uncomment the ldapContextSource bean and add the following informations:
  • constructor-arg: the URL of the LDAP server (including the baseDN)
  • userDN: the DN (distinguished name) of the LDAP administrator
  • password: the password of the LDAP administrator
<!-- For LDAP authentication -->
   
   <bean id="ldapContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
     <constructor-arg value="ldap://192.168.71.131:389/dc=maxcrc,dc=com"/>
     
     <property name="userDn"><value>cn=Manager,dc=maxcrc,dc=com</value></property>
     <property name="password"><value>secret</value></property>
          
   </bean>
Finally, we need to specify the users search parameters in the LDAP directory. In the same file /jasperserver-pro/WEB-INF/applicationContext-security.xml, we have to locate and uncomment the userSearch bean and add the following informations:
  • A branch in the LDAP directory where the users are located: if empty, the application will search the entire LDAP directory, starting from the baseDN
  • A filter expression that matches an attribute (or a combination of attributes) with the login name. The login name indicated by the user must is substituted with the {0} placeholder
  • Whether or not the search must be extended to eventual subTrees
<!-- For LDAP authentication
   This bean is not used by default -->
   
   <bean id="userSearch"
            class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
     <constructor-arg index="0">
       <value>ou=People</value>
     </constructor-arg>
     <constructor-arg index="1">
       <value>(cn={0})</value>
     </constructor-arg>
     <constructor-arg index="2">
       <ref local="ldapContextSource" />
     </constructor-arg>            
     <property name="searchSubtree">
       <value>true</value>
     </property>            
   </bean>       
For this example, we limit the search inside the People organizational unit, and we search all nodes that have the cn attribute equal to the login name.
Now we just have to uncomment the ldapAuthenticationProvider, and specify we want to use the userSearch bean to search the users:
<!-- For LDAP authentication -->
<bean id="ldapAuthenticationProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
     <constructor-arg>
       <bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
          <constructor-arg><ref local="ldapContextSource"/></constructor-arg>
          <!-- property name="userDnPatterns"><list><value>uid={0}</value></list></property -->
          <property name="userSearch" ref="userSearch"/>
       </bean>
     </constructor-arg>
    ...
    </bean>
These are all the steps necessary in order to authenticate an external user defined in a LDAP directory in JasperReports Server. In the next post, we'll see the implementation of a simple multi-tenancy system, and the mapping of external roles in JasperReports Server.

No comments:

Post a Comment