Marcel Gascoyne

JAAS with active directory authentication in a web application

This is a sample to use JAAS authentication with a windows active directory server. I use a Sun Java System Application Server, so the steps with other servers could be different.

Step 1: Defining LDAP realm

In this example you must define a LDAP realm named «ads-realm» with the following parameters:

Realm class:

com.sun.enterprise.security.auth.realm.ldap.LDAPReam

Properties:

directory            = ldap://ads.host.name:389
base-dn              = DC=ads,DC=domain,DC=com
search-bind-dn       = user
search-bind-password = password
search-filter        = (&(objectClass=user)(sAMAccountName=%s))
group-search-filter  = (&(objectClass=group)(member=%d))
jaas-context         = ldapRealm

You must change directory, base-dn, search-bind-dn and search-bind-password to your active directory configuration. The «search-bind-dn» and «search-bind-password» parameters are needed, because with default settings active directory doesn’t allow anonymous users to browse the directory.

Step 2: Setting the following JVM Switch for refferals

The following JVM switch is needed with active directory LDAP servers:

-Djava.naming.referral=follow

Add this switch to your server startup script or with the admin console.

Step 3a: Basic authentication

Add the following section to your web.xml or go to Step 3b for form
based authentication.

<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>ads-realm</realm-name>
</login-config>

Step 3b: Form based authentication

Add the following section to your web.xml:

<login-config>
  <auth-method>FORM</auth-method>
  <realm-name>ads-realm</realm-name>
  <form-login-config>
    <form-login-page>/login.html</form-login-page>
    <form-error-page>/login.html</form-error-page>
  </form-login-config>
</login-config>

Create the page /login.html with a least the following code:

<html>
  <head/>
  <body>
    <form action="j_security_check" method="post">
      Username: <input type="text" name="j_username"><br/>
      Password: <input type="password" name="j_password"><br/>
      <input type="submit" value="Login"/>
    </form>
  </body>
</html>

Step 4: Adding security role to web.xml

Add at least one security role to your web.xml, in this example «userRole».

<security-role>
  <role-name>userRole</role-name>
</security-role>

Step 5: Adding security constraint to web.xml

Now we must create a security constraint and the path to the pages we want to allow only authenticated access. In this sample the access to the folder /pages/ is resticted to authenticated users in role «userRole».

<security-constraint>
  <display-name>SecurityConstraint</display-name>
  <web-resource-colletion>
    <web-resource-name>SecuredFolder</web-resource-name>
      <url-pattern>/pages/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>userRole</role-name>
    </auth-constraint>
  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee>
  </user-data-constraint>
</security-constraint>

Step 6: Create role mapping between active directory group and role

Role mappings are defined in sun-web.xml for the Sun Java System Application Server, so add the following section:

<security-role-mapping>
  <role-name>userRole</role-name>
  <group-name>users</group-name>
</security-role-mapping>

This maps the active directory group «users» to our role «userRole»,
so only users in the group «users» can access our secured folder.

ICEFaces installation for NetBeans IDE

ICEFaces is a Java Server Faces component library. To integrate ICEFaces into the NetBeans IDE and the Visual Web Pack the following steps are necessary.

Download of ICEFaces components

The following downloads from the ICEFaces website are needed:

  • ICEfaces-<version>-libs-NetBeans.zip
  • ICEfaces-NetBeans-IDE-<version>.zip
  • ICEfaces-<version>-complib-NetBeans.zip

Installation of ICEFaces runtime library

Unpack the file ICEfaces-<version>-libs-NetBeans.zip and import the included com-icesoft-ide-netbeans-libs-module.nbm module with the NetBeans Update Manager.

Installation of ICEFaces IDE integration

Unpack the file ICEfaces-NetBeans-IDE-<version>.zip and install the module com-icesoft-faces-vwp-ide.nbm. This module must also be installed with the NetBeans Update Manager.

Installation of ICEFaces component library

Unpack file icefaces-webui.complib from ICEfaces-<version>-complib-NetBeans.zip and copy it to your <netbeans-install-dir>/rave2.0/samples folder.

Import the component library with the Component Library Manager under «Tools->Component Library Manager» into your IDE.

Use of ICEFaces components in a Visual Web Pack project

To use the ICEFaces components in a Visual Web Pack application you must add the ICEFaces Component Suite to your project.

Using Jasper Reports with Visual Web Pack

This tutorial illustrates the use of Jasper Reports with a Visual Web Pack application.

Register Jasper Reports library

Use the NetBeans Library Manager to create a library for the Jasper Reports class libraries. You need at least the following files from the distribution:

  • dist/jasperreports-<version>.jar
  • lib/commons-beanutils-1.7.jar
  • lib/commons-collections-2.1.jar
  • lib/commons-digester-1.7.jar
  • lib/commons-logging-1.0.2.jar
  • lib/itext-1.3.1.jar

Register Jasper Reports image servlet

The image servlet is needed if you want html rendered reports (also without any graphical elements, because report placeholders uses images from this servlet). So you must register it in the web.xml configuration file. You can use the NetBeans web.xml editor to do so.

Servlet name  : ImageServlet
Servlet class : net.sf.jasperreports.j2ee.servlets.ImageServlet
URL           : /image

Insert methods for report output to application bean

The following methods in the application bean can be used to output a precompiled report as html or pdf. In this sample a collection of java objects is used as data source. For other data sources see the Jasper Reports documentation.

/**
 * Output Jasper Report
 *
 * @param filename Precompiled report filename
 * @param type Content type of report ("application/pdf" or "text/html")
 * @param data Collection of value objects
 */
public void jasperReport( String filename, String type, Collection data ) {
  jasperReport( filename, type, data, new HashMap() );
}

/**
 * Output Jasper Report
 *
 * @param filename Precompiled report filename
 * @param type Type of report ("application/pdf" or "text/html")
 * @param data Collection of value objects
 * @param params Map with parameters
 */
public void jasperReport( String filename, String type, Collection data, Map params ) {
  final String[] VALID_TYPES = { "text/html", "application/pdf" };
  // First check if type is supported
  boolean found = false;
  for ( int i = 0; i < VALID_TYPES.length; i++ ) {
    if ( VALID_TYPES[i].equals( type ) ) {
      found = true;
      break;
    }
  }

  if ( !found ) {
    throw new IllegalArgumentException( "Report type '" + type + "' not supported." );
  }

  // InputStream for compiled report
  ExternalContext econtext = getExternalContext();
  InputStream stream = econtext.getResourceAsStream( filename );

  if ( stream == null ) {
    throw new IllegalArgumentException( "Report '" + filename + "' could not be opened." );
  }

  // Use collection as data source
  JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource( data );
  JasperPrint jasperPrint = null;

  try {
    jasperPrint = JasperFillManager.fillReport( stream, params, ds );
  } catch ( RuntimeException e ) {
    throw e;
  } catch ( Exception e ) {
    throw new FacesException( e );
  } finally {
    try {
      stream.close();
    } catch ( IOException e ) {
    }
  }

  // Configure exporter and set parameters
  JRExporter exporter = null;
  HttpServletResponse response = (HttpServletResponse) econtext.getResponse();
  FacesContext fcontext = FacesContext.getCurrentInstance();

  try {
    response.setContentType( type );

    if ( "application/pdf".equals( type ) ) {
      exporter = new JRPdfExporter();
      exporter.setParameter( JRExporterParameter.JASPER_PRINT, jasperPrint );
      exporter.setParameter( JRExporterParameter.OUTPUT_STREAM,
        response.getOutputStream() );
    } else if ( "text/html".equals( type ) ) {
      exporter = new JRHtmlExporter();
      exporter.setParameter( JRExporterParameter.JASPER_PRINT, jasperPrint );
      exporter.setParameter( JRExporterParameter.OUTPUT_WRITER, response.getWriter() );
      HttpServletRequest request = (HttpServletRequest)
        fcontext.getExternalContext().getRequest();
      request.getSession().setAttribute(
        ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint );
      exporter.setParameter( JRHtmlExporterParameter.IMAGES_MAP, new HashMap() );
      exporter.setParameter(
        JRHtmlExporterParameter.IMAGES_URI,
        request.getContextPath() + "/image?image=" );
    }
  } catch ( RuntimeException e ) {
    throw e;
  } catch ( Exception e ) {
    throw new FacesException( e );
  }

  // Export report
  try {
    exporter.exportReport();
  } catch ( RuntimeException e ) {
    throw e;
  } catch ( Exception e ) {
    throw new FacesException( e );
  }

  // Tell JavaServer faces that no more processing is necessary
  fcontext.responseComplete();
}

Start report output from page bean

The output of a report can initiated from a ActionEvent with the following code:

try {
  getApplicationBean().jasperReport(
    "/reports/report.jasper",
    "application/pdf",
    getSessionBean().getSuchergebnisDataProvider().getList() );
} catch ( Exception e ) {
  Logger.getLogger(getClass().getName()).severe( e.getMessage() );
}

return null;

NetBeans CVS access with SSH

If your ssh key is secured with a password you need to run a ssh agent (e.g. PuTTY agent) on your client machine, because NetBeans has no support for ssh passwords.

Enter your CVS_ROOT in the following syntax:

:ext:<user>@<host>:<path-to-cvsroot>

You must use external shell command to execute ssh, e.g. for Putty under windows environment:

C:\Program files\Putty\plink.exe -ssh -i <path-to-ssh-keyfile>

Postfix setup for SSL and TLS

To use SSL and TLS with the postfix mailer daemon you must change settings in the /etc/postfix/main.cf configuration file:

# tls config
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_CAfile = /etc/postfix/ssl/demoCA/cacert.pem
smtpd_tls_cert_file = /etc/postfix/ssl/server-crt.pem
smtpd_tls_key_file = /etc/postfix/ssl/server-key.pem
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom
tls_random_prng_update_period = 3600s

You also need a SSL certificate for your mail server. Create it with the following commands:

mkdir /etc/postfix/ssl
cd /etc/postfix/ssl/

# Create new local certification authority (if not already present)
/usr/share/ssl/misc/CA.pl -newca

# Create RSA certificate
openssl req -new -nodes -keyout server-key.pem -out server-req.pem -days 365
openssl ca -out server-crt.pem -infiles server-req.pem
chmod 644 server-crt.pem demoCA/cacert.pem
chmod 400 server-key.pem

Now you must remove the comment mark “#” for SMTPS and TLS manager in the /etc/postfix/master.cf configuration file:

smtps     inet  n       -       n       -       -       smtpd -o smtpd_tls_wrappermode=yes
tlsmgr    unix  -       -       n       1000?   1       tlsmgr