Core Security Patterns: Best Practices and Strategies for J2EE, Web Services, and Identity Management

Stand-alone clients, rich clients, or Java applets are commonly used as alternatives to Web-based clients. These clients are adopted particularly to support dynamic content and client-side business scenarios as well as to overcome limitations of Web pages. Clients are usually not considered J2EE components, because they don't make use of the J2EE container services provided by the J2EE server environment. In most scenarios, clients connect with the J2EE server-deployed applications via HTTP connections, remote-method invocation, or asynchronous messaging. Typically rich clients use HTTP as a transport to interact with JSP or Servlet components, RMI-IIOP for interacting with EJB components, and JAX-RPC (SOAP-RPC) for interacting with J2EE Web services components.

In a J2EE environment, a Java client depends on an application client container (ACC) to provide the client-specific artifacts and services for looking up and then communicating with server-deployed components, particularly EJBs, JMS Queues, data sources, and so forth. An application client container is usually packaged as a JAR file that includes a deployment descriptor (application-client.xml) specifying the J2EE deployed components and their associated resources. If the J2EE components are secured, the client can make use of the deployment descriptor to specify security-specific information.

In general, to enforce J2EE security mechanisms from a Java client, the following options are considered.

HTTPS Connection

Using JSSE mechanisms, clients can create HTTP/SSL-based URL connections with J2EE-deployed components such as JSPs and Servlets. Using two-way SSL allows the client to confirm the user identity with the J2EE component by verifying client's certificates issued by a CA listed in the server's list of trusted CAs. Using JSSE for HTTPS connection, it is necessary to import the trusted certificates into the respective client and server keystores.

The code snippet in Example 5-22 shows how to use HTTP/SSL in a Java client code.

Example 5-22. Using HTTPS connection from a Java client code

// Dynamically add Sun's SSL provider Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); // Set the system property for Sun's implementation of // HTTPS URL handler System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol"); URL securesite = new URL("https://www.verisign.com/"); BufferedReader in = new BufferedReader( new InputStreamReader( securesite.openStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close();

If the client uses a proxy server, the proxy-specific properties can be set as shown in Example 5-23.

Example 5-23. Setting proxy-specific properties in client code

// set name of proxy server System.setProperty("https.proxyHost", "proxy"); // set port number for proxy server System.setProperty("https.proxyPort", "8080");

For more information about JSSE API mechanisms, refer to Chapter 4, "Java Extensible Security Architecture and APIs."

JAAS Client-Side Callbacks

A client can make use of the JAAS callback handlers to interact with a JAAS LoginModule plugged in a J2EE application environment. A typical JAAS LoginModule implements the javax.security.auth.callback.CallbackHandler interface for obtaining client input such as username and password to perform authentication. For example, the implementation of a callback handler using a Java GUI application might prompt the user with a GUI window to provide user credentials, or the implementation of a callback handler for a command-line tool might simply prompt the user for input directly from the OS prompt. In a typical scenario, the JAAS LoginModule initiates an array of callbacks to the callback handler's handle method (e.g., a NameCallback for the username and a PasswordCallback for the password), and the callback handler performs the requested user interaction and sets appropriate values in the callbacks. To support this, the client-side callback initiates the client login prompt to obtain the username and password. The snippet in Example 5-24 shows a JAAS client that uses a callback handler to perform authentication before invoking a J2EE component.

Example 5-24. J2EE client using a JAAS Client callback handler

LoginContext lc = null; // Create a LoginContext try { lc = new LoginContext("MyJAASClient", new MyCallbackHandler(username, password, url)); } catch (LoginException le) { System.err.println("Failed: Creating LoginContext. "+ le.getMessage()); System.exit(-1); } catch (SecurityException se) { System.err.println("Failed: Creating LoginContext. " + se.getMessage()); System.exit(-1); } // Call the login method of the LoginModule try { loginContext.login( ); } catch (Exception e) { } // Now create the initial context // for Looking up the J2EE component Initial Context ic = new InitialContext(); // Invoke the J2EE component

For more information about implementing JAAS LoginModules and JAAS Clients, refer to Chapter 4, "Java Extensible Security Architecture and APIs."

Secure J2ME Clients

J2ME clients may interact remotely with a J2EE application server and access its deployed components. However, since J2ME clients have limited GUI capabilities compared to traditional Java clients, J2ME clients should only be considered when mobility and remote access are key deployment requirements.

With MIDP 2.0 implementation, J2ME devices support using HTTP/SSL communication, specifically the TLS 1.0, SSLv3, WTLS (Wireless Transport Layer Security), and WAP TLS Profile and Tunneling Specifications. This allows establishing HTTPS connections with J2EE Web-tier components and ensures authentication, integrity, and confidentiality of all data exchanged between the J2ME device and the J2EE server. MIDP 2.0 provides a javax.microedition.io.HttpsConnection interface, an extension of the HttpConnection. This interface includes a getSecurityInfo() method that returns an instance of another interface, SecurityInfo. The SecurityInfo interface provides methods that return information about a secure connectiondetails such as protocol name, protocol version, cipher suite, server certificate, and so forth. When using client-side artifacts such as an application client container, it is important to note that the provisioned component must comply with the appropriate J2ME profile.

The snippet in Example 5-25 illustrates how a J2EE client establishes an SSL connection and obtain the server certificate information.

Example 5-25. J2ME client using an SSL connection

String url = "https://www.cspsecurity.org/"; // Create an HTTPS connection HttpsConnection hc = null; // Use the Connector.open method hc = (HttpsConnection)Connector.open(url); // Obtain the security information SecurityInfo info = hc.getSecurityInfo(); Certificate c = info.getServerCertificate(); String name = c.getIssuer();

MIDP 2.0 also introduced the concept of trusted MIDlets that can be digitally signed and verified. With signed MIDlets, it is possible to authenticate and verify the integrity of the MIDlet suite. For more information about MIDlet security features, refer to Chapter 3, "The Java 2 Platform Security."

Категории