Thursday, October 31, 2013

@Autowired in web applications

"Marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities." (http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/beans/factory/annotation/Autowired.html)

Almost all samples on this topic use command line Java applications that programatically load the configuration file that maps the interface to its implementation class. In JSF based applications use the context param tag in web.xml to achieve the same result.

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:/security/samlUserDetailsService4Autowire.xml
            classpath:/security/securityContext.xml
        </param-value>
</context-param>
Please notice that the order of configuration files is important and is dictated by dependency injection 'dependencies' (at the moment of injection the required instances to be injected must already exist)

Wednesday, October 23, 2013

Decoding SAML Request/Response

You can use online decoder provided by ssocircle: https://idp.ssocircle.com/sso/toolbox/samlDecode.jsp
If sent as URL parameter the request/response must be decoded with the redirect option.
The actual algorithm for obtaing the encoded string is as follows:
  1. Gzip deflate the request/response if sent as query parameter (no change for POST parameters)
  2. Convert to Base64
  3. URL encode the result

Configure Galssfish (3.1.2.2) for HTTPS


  1. Prepare a certificate (issued for the FQDN of the server running Glassfish) in PKCS#12 format (p12 extension) containing the private/public key pair; OpenSSL can be used to generate a CA and generate afterwards test certificates
  2. In target domains/<domanin>/config/cacerts.jks add* CA public certificate; default keystore password is 'changeit'
  3. In target domains/<domanin>/config/keystore.jks add the p12 certificate; use the same password as the keystore ('default value 'changeit')
  4. Open adnin console, go to server configuration and expand it to Network Config->Network Listners->network-listner-2, SSL tab.
  5. Replace the default test certificate name (s1as) with the keystore name of the newly added certificate
  6. Apply changes and restart glassfish
*You can use Portecle GUI based tool to manage keystores

Run Spring SAML Extension sample app.

Prerequisites:

  1. NetBeans 7.4
  2. Glassfish 3.1.2.2
  3. A PKCS#12 format cerificate for SAML requests signing
  4. Spring SAML Extension sample app downloaded (http://docs.spring.io/spring-security/site/extensions/saml/)

  • Add the certificate in  samlKeystore.jks (in resources\security)
  • Open project in NetBeans
  • Change the default securityContext.xml (will be used later):
    • configure the newly added certificate in keyManagerBean as an entry in constructor parameters
                             <entry key="localhostsaml" value="nalle123"/>
    • configure the metadataGeneratorBean constructor parameter:

                            <bean class="org.springframework.security.saml.metadata.MetadataGenerator">
                               <property name="entityId" value="urn:myid:saml"/>
                               <property name="signMetadata" value="false"/>
                               <property name="bindingsSSO" >
                                 <list>
                                    <value>POST</value>
                                 </list>
                              </property>
                           </bean>
  • save the  and NetBeans will deploy the war
  • run the metadata generation page : https:// localhost.myserver.local:8181/spring-security-saml2-sample/saml/web/metadata; use the real FQDN so that metadata will be generated with actual values
  • Click on the link "Generate new service provider metadata)
  • Change the values of:
    • Entity ID and Entity alias to same urn as the entityId previously configured (eg urn:myid:saml)
    • SigningKey and EncriptionKey to the one added in samlKeystore.jks (localhostsaml in our sample)
    • Sign Metadata: No
    • Single sign-on bindings: unckeck Artifact and choose as default the POST one
    • Enable IDP Discovery profile:: No
  • Press Generate Metadata
  • Copy The content of Metadata texta area andcopy the content in a newly created sp.xml, placed in resources\security
  • In securityContext.xml add a constructor parameter for "metadata" bean:
                <bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
                    <constructor-arg>
                        <bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
                            <constructor-arg>
                                <value type="java.io.File">classpath:security/sp.xml</value>
                            </constructor-arg>
                            <property name="parserPool" ref="parserPool"/>
                        </bean>
                    </constructor-arg>
                    <constructor-arg>
                        <bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
                            <property name="local" value="true"/>
                            <property name="alias" value="urn:myid:saml"/>
                            <property name="securityProfile" value="metaiop"/>
                            <property name="sslSecurityProfile" value="pkix"/>
                            <property name="signingKey" value="localhostsaml"/>
                            <property name="encryptionKey" value="localhostsaml"/>
                            <property name="requireArtifactResolveSigned" value="false"/>
                            <property name="requireLogoutRequestSigned" value="false"/>
                            <property name="requireLogoutResponseSigned" value="false"/>
                            <property name="idpDiscoveryEnabled" value="false"/>
                        </bean>
                    </constructor-arg>
                </bean> 
Please notice that the ExtendedMetadata   content is copy/pasted from metadata generation result (Configuration text area)  
  • Un comment and update the tag, values is actually the value of the alias (we have used the same value for Id and alias): 
             <property name="hostedSPName" value="urn:myid:saml"/>
  • Be sure that the only uncommented tag for defaultIDPis the following:
             <property name="defaultIDP " value="http://idp.ssocircle.com"/>
  • Go to http://www.ssocircle.com/en/ and create an account
  • After login go to Manage Metadata and create a new Service Provider:
    • Provide the FDQN as the entityId (urm:myid:saml in our sample)
    • Mark all attributes
    • Paste the content of sp.xml in the metadata information text area
  • Log out from ssocircle
  • Run the application; you should be redirected to ssocircle and after entering usernam/password redirected back to index.jsp showing information received in  SAML Response

Saturday, June 29, 2013

JSF caching of javascript, css, etc

In order to have static resources cached change in web.xml from
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
to
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Production</param-value>
    </context-param>
This will allow caching of static resources fro 10 minutes;in order to change the default value add another context parameter: com.sun.faces.defaultResourceMaxAge (the default value of this parameter is 604800 ~ 10 mins)

Wednesday, April 17, 2013

JasperReports

iReports

After installing add the JDBC DataSource jar in iReports Classpath through Tools->Options-Classpath (be sure to add the jar, not the folder); restart iReports
Create a DataSource (no menu option available, just click the plug-in socket icon); be sure you add the database name at the end of the URL
Now you can create a new report and modify the report query. You can define report default values for parameters as follows (please notice that parameters are strong typed so you must create an instance of the java class):

  • String: enclose the desired value in double quotes
  • Date:
  1. new Date()
  2. new Date(113,0,1)
The second expression will initialize the default value to 1st of January 2013 (!):year+1900,month+1

Formatting dates:

  • add an expression in the report
  • change the expression text with something like this:
  • "From "+(new SimpleDateFormat("yyyy/MM/dd")).format($P{DateStart})+" to "+(new SimpleDateFormat("yyyy/MM/dd")).format($P{DateEnd})

JSF and JasperReports

Add the required jars (found in jasper reports distribution in dist and lib sub-directories) as project references. Minimal (depending on used functionality):
  • jasperreports
  • all commons
  • iText
  • groovy-all
Deploy compiled report in resources/jsrep (for instance) project sub-directory.
In managed bean you can use the following code to show the report in PDF format (the sample code uses PrimeFaces file download component, see the showcase):

      InputStream stream = ((ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext()).getResourceAsStream("/resources/jsrep/Report.jasper"); 
       JasperReport report = (JasperReport) JRLoader.loadObject(stream);
       Map<String, Object> params = new HashMap<String, Object>();
       params.put("Param", 494);
       JasperPrint jasperPrint = JasperFillManager.fillReport(report, params, ds.getConnection());
       ByteArrayOutputStream baos=new ByteArrayOutputStream();
       JasperExportManager.exportReportToPdfStream(jasperPrint,baos );
       ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
       return new DefaultStreamedContent(bais, "application/pdf", "report.pdf"); 
The data source can be obtained through injection, like
@Resource(name="jdbc/MyDataSource")
DataSource ds;
In order to export to XLS add poi jar to solution and use the following code:

        InputStream stream = ((ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext()).getResourceAsStream("/resources/jsrep/Report.jasper");
        JasperReport report = (JasperReport) JRLoader.loadObject(stream);
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("Param", 123);
        JasperPrint jasperPrint = JasperFillManager.fillReport(report, params, ds.getConnection());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        JRXlsExporter exporterXLS = new JRXlsExporter();
        exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT, jasperPrint);
        exporterXLS.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, baos);
        exporterXLS.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
        exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
        exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
        exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
        exporterXLS.setParameter(JRXlsExporterParameter.PASSWORD, null);
        exporterXLS.exportReport();
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        return new DefaultStreamedContent(bais, "application/vnd.ms-excel", "report.xls");

Creating reports that will be exported to XLS can be tricky: be sure that fields are top aligned pixel-perfect otherwise they will not be shown or shown in an unexpected manner in resulting XLS



Monday, April 8, 2013

Configure MySQL jdbc resource


  1. Copy the MySQL jdbc driver (jar file) in Glassfish lib directory and restart Glassfish
  2. In the glassfish administration console (site) go to Resources\JDBC\JDBC ConnectionPools
  3. Create a new pool of type javax.sql.DataSource and choose MySQL as the database vendor
  4. Fill in: server, user, password, database and, very important, check the URL to contain the database name (for some reason or under some circumstances it is not correctly filled in)
  5. Try Ping, should be successfull
  6. Now create the jdbc Resource, etc