![]() |
![]() |
e-docs > WebLogic Server > Programming WebLogic Security > Using SSL Authentication in Java Clients |
Programming WebLogic Security
|
Using SSL Authentication in Java Clients
The following topics are covered in this section:
JSSE is a set of packages that support and implement the SSL and TLS v1 protocols, making those capabilities programmatically available. BEA WebLogic Server provides Secure Sockets Layer (SSL) support for encrypting data transmitted between WebLogic Server clients and servers, Java clients, Web browsers, and other servers.
WebLogic Server's Java Secure Socket Extension (JSSE) implementation can be used by WebLogic clients, but is not required. Other JSSE implementations can be used for their client-side code outside the server as well.
The following restrictions apply when using SSL in WebLogic server-side applications:
WebLogic Server uses the HTTPS port for SSL. Only SSL can be used on that port. SSL encrypts the data transmitted between the client and WebLogic Server so that the username and password do not flow in clear text.
Note: In order to implement security in a WebLogic client, you must install the WebLogic Server software distribution kit on the Java client.
Java clients use the Java Naming and Directory Interface (JNDI) to pass credentials to WebLogic Server. A Java client establishes a connection with WebLogic Server by getting a JNDI InitialContext. The Java client then uses the InitialContext to look up the resources it needs in the WebLogic Server JNDI tree.
Note: JAAS is the preferred method of authentication, however, the Authentication provider's LoginModule only supports username and password authentication. Thus, for client certificate authentication (also referred to as two-way SSL authentication), you should use JNDI. To use JAAS for client certificate authentication, you must write a custom Authentication provider whose LoginModule does certificate authentication.
To specify a user and the user's credentials, set the JNDI properties listed in the Table 4-1.
Provides an entry point into the WebLogic Server environment. The class weblogic.jndi.WLInitialContextFactory is the JNDI SPI for WebLogic Server. |
|
Specifies the host and port of the WebLogic Server that provides the name service. For example: t3s://weblogic:7002. |
|
Specifies the identity of the user when that user authenticates to the default (active) security realm. |
These properties are stored in a hash table that is passed to the InitialContext constructor. Notice the use of t3s, which is a WebLogic Server proprietary version of SSL. t3s uses encryption to protect the connection and communication between WebLogic Server and the Java client.
Listing 4-1 demonstrates how to use one-way SSL certificate authentication in a Java client. For a two-SSL authentication code example, see Listing 4-5.
Listing 4-1 Example of One-Way SSL Authentication Using JNDI
...
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3s://weblogic:7002");
env.put(Context.SECURITY_PRINCIPAL, "javaclient");
env.put(Context.SECURITY_CREDENTIALS, "javaclientpassword");
ctx = new InitialContext(env);
Note: For information on JNDI contexts and threads and how to avoid potential JNDI context problems, see "JNDI Contexts and Threads" and "How to Avoid JNDI Context Problems" in the Programming WebLogic JNDI.
SSL Certificate Authentication Development Environment
The following topics are covered in this section:
To implement Java clients that use SSL authentication on WebLogic Server, you use a combination of Java SDK 1.3 application programming interfaces (APIs) and WebLogic APIs.
Table 4-2 lists and describes the Java SDK APIs packages used to implement certificate authentication. The information in Table 4-2 is taken from the Java SDK API documentation and annotated to add WebLogic Server specific information. For more information on the Java SDK APIs, see the Javadocs at http://java.sun.com/j2ee/sdk_1.3/techdocs/api/index.html.
Table 4-3 lists and describes the WebLogic APIs used to implement certificate authentication. For more information, see Javadocs for WebLogic Classes.
SSL Client Application Components
At a minimum, an SSL client application comprises the following components:
The HostnameVerifier implements the weblogic.security.SSL.HostnameVerifierJSSE interface. It provides a callback mechanism so that implementers of this interface can supply a policy for handling the case where the host that is being connected to and the server name from the certificate Subject Distinguished Name (SubjectDN) must match.
The HandshakeCompletedListener implements the javax.net.ssl.HandshakeCompletedListener interface. It defines how the SSL client receives notifications about the completion of an SSL handshake on a given SSL connection. It also defines the number of times an SSL handshake takes place on a given SSL connection.
For a complete working SSL authentication client that implements the components described here, see the SSLClient sample application in the SAMPLES_HOME\server\src\examples\security\sslclient directory provided with WebLogic Server.
For more information on JSSE authentication, see Sun's Java Secure Socket Extension (JSSE) 1.0.3 API User's Guide available at http://java.sun.com/products/jsse/doc/guide/API_users_guide.html.
Writing Applications that Use SSL
This section covers the following topics:
Communicating Securely From WebLogic Server to Other WebLogic Servers
You can use a URL object to make an outbound SSL connection from a WebLogic Server instance acting as a client to another WebLogic Server instance. The weblogic.net.http.HttpsURLConnection class provides a way to specify the security context information for a client, including the digital certificate and private key of the client.
The weblogic.net.http.HttpsURLConnection class provides methods for determining the negotiated cipher suite, getting/setting a host name verifier, getting the server's certificate chain, and getting/setting an SSLSocketFactory in order to create new SSL sockets.
The SSLClient code example uses the weblogic.net.http.HttpsURLConnection class to make an outbound SSL connection. The SSLClient code example is available in the examples.security.sslclient package in the SAMPLES_HOME\server\src\examples\security\sslclient directory.
This section describes, by way of example, how to write various types of SSL clients. Examples of the following types of SSL clients are provided:
SSL Client License Requirement: Any stand-alone Java client that uses WebLogic SSL classes (weblogic.security.SSL) to invoke an Enterprise JavaBean (EJB) must use the BEA license file. When you run your client application, set the following system properties on the command line:
Where license_file_directory refers to the directory that contains the BEA license file (license.bea). Here is an example of a run command that uses the default location of the license file (c:\bea):
java -Dbea.home=c:\bea \
-Djava.protocol.handler.pkgs=com.certicom.net.ssl my_app
The SSLClient sample demonstrates how to use the WebLogic SSL library to make outgoing SSL connections using URL and URLConnection objects. It shows both how to do this from a stand-alone application as well as from a servlet in WebLogic Server.
Note: When making an outgoing SSL connection, a WebLogic Server instance uses the server's certificate. When communicating to either the same or another WebLogic Server instance with two-way SSL, the originating server's certificate will be verified against the client root CA list in the receiving WebLogic Server instance.
Listing 4-2 shows a sample SSLClient. This code is taken from the SSLClient.java file located at SAMPLES_HOME\server\src\examples\security\sslclient.
Listing 4-2 SSL Client Sample Code
package examples.security.sslclient;
import java.io.File;
import java.net.URL;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Hashtable;
import java.security.Provider;
import javax.naming.NamingException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletOutputStream;
import weblogic.net.http.*;
import weblogic.jndi.Environment;
/** SSLClient is a short example of how to use the SSL library of
* WebLogic to make outgoing SSL connections. It shows both how to
* do this from a stand-alone application as well as from within
* WebLogic (in a Servlet).
*
* Be careful to notice that the WebLogic Server, when making an
* outgoing SSL connection, will use that instance of the server's
* certificate. When communicating to either the same or another
* WebLogic Server with two-way SSL, the originating server's
* certificate will be verified against the client root CA list in
* the receiving WebLogic Server.
*
* @author Copyright (c) 1999-2002 by BEA Systems, Inc. All Rights Reserved.
*/
public class SSLClient {
public void SSLClient() {}
public static void main (String [] argv)
throws IOException {
if ((!((argv.length == 4) || (argv.length == 5))) ||
(!(argv[0].equals("wls")))
) {
System.out.println("example: java SSLClient wls
server2.weblogic.com 80 443 /examplesWebApp/SnoopServlet.jsp");
System.exit(-1);
}
try {
System.out.println("----");
if (argv.length == 5) {
if (argv[0].equals("wls"))
wlsURLConnect(argv[1], argv[2], argv[3], argv[4], System.out);
} else { // for null query, default page returned...
if (argv[0].equals("wls"))
wlsURLConnect(argv[1], argv[2], argv[3], null, System.out);
}
System.out.println("----");
} catch (Exception e) {
e.printStackTrace();
printSecurityProviders(System.out);
System.out.println("----");
}
}
private static void printOut(String outstr, OutputStream stream) {
if (stream instanceof PrintStream) {
((PrintStream)stream).print(outstr);
return;
} else if (stream instanceof ServletOutputStream) {
try {
((ServletOutputStream)stream).print(outstr);
return;
} catch (IOException ioe) {
System.out.println(" IOException: "+ioe.getMessage());
}
}
System.out.print(outstr);
}
private static void printSecurityProviders(OutputStream stream) {
StringBuffer outstr = new StringBuffer();
outstr.append(" JDK Protocol Handlers and Security Providers:\n");
outstr.append(" java.protocol.handler.pkgs - ");
outstr.append(System.getProperties().getProperty(
"java.protocol.handler.pkgs"));
outstr.append("\n");
Provider[] provs = java.security.Security.getProviders();
for (int i=0; i<provs.length; i++)
outstr.append(" provider[" + i + "] - " + provs[i].getName() +
" - " + provs[i].getInfo() + "\n");
outstr.append("\n");
printOut(outstr.toString(), stream);
}
private static void tryConnection(java.net.HttpURLConnection connection,
OutputStream stream)
throws IOException {
connection.connect();
String responseStr = "\t\t" +
connection.getResponseCode() + " -- " +
connection.getResponseMessage() + "\n\t\t" +
connection.getContent().getClass().getName() + "\n";
connection.disconnect();
printOut(responseStr, stream);
}
/*
* This method contains an example of how to use the URL and
* URLConnection objects to create a new SSL connection, using
* WebLogic SSL client classes.
*/
public static void wlsURLConnect(String host, String port,
String sport, String query,
OutputStream out) {
try {
if (query == null)
query = "/examplesWebApp/index.jsp";
// The following protocol registration is taken care of in the
// normal startup sequence of WebLogic. It can be turned off
// using the console SSL panel.
//
// We duplicate it here as a proof of concept in a stand alone
// java application. Using the URL object for a new connection
// inside of WebLogic would work as expected.
java.util.Properties p = System.getProperties();
String s = p.getProperty("java.protocol.handler.pkgs");
if (s == null) {
s = "weblogic.net";
} else if (s.indexOf("weblogic.net") == -1) {
s += "|weblogic.net";
}
p.put("java.protocol.handler.pkgs", s);
System.setProperties(p);
printSecurityProviders(out);
// end of protocol registration
printOut(" Trying a new HTTP connection using WLS client classes -
\n\thttp://" + host + ":" + port + query + "\n", out);
URL wlsUrl = null;
try {
wlsUrl = new URL("http", host, Integer.valueOf(port).intValue(), query);
weblogic.net.http.HttpURLConnection connection =
new weblogic.net.http.HttpURLConnection(wlsUrl);
tryConnection(connection, out);
} catch (Exception e) {
printOut(e.getMessage(), out);
e.printStackTrace();
printSecurityProviders(System.out);
System.out.println("----");
}
printOut(" Trying a new HTTPS connection using WLS client classes -
\n\thttps://" + host + ":" + sport + query + "\n", out);
wlsUrl = new URL("https", host, Integer.valueOf(sport).intValue(), query);
weblogic.net.http.HttpsURLConnection sconnection =
new weblogic.net.http.HttpsURLConnection(wlsUrl);
// Only when one has a two-way SSL connection, i.e. ClientCertificateEnforced
// is selected in the server under the SSL tab, the following private key
// and the client cert chain is used.
File ClientKeyFile = new File ("clientkey.pem");
File ClientCertsFile = new File ("client2certs.pem");
if (!ClientKeyFile.exists() || !ClientCertsFile.exists())
{
System.out.println("Error : clientkey.pem/client2certs.pem
is not present in this directory.");
System.out.println("To create it run - ant createmycerts.");
System.exit(0);
}
InputStream [] ins = new InputStream[2];
ins[0] = new FileInputStream("client2certs.pem");
ins[1] = new FileInputStream("clientkey.pem");
String pwd = "clientkey";
sconnection.loadLocalIdentity(ins[0], ins[1], pwd.toCharArray());
tryConnection(sconnection, out);
} catch (Exception ioe) {
printOut(ioe.getMessage(), out);
ioe.printStackTrace();
}
}
}
The SSLSocketClient sample demonstrates how to use SSL sockets to go directly to the secure port to connect to a JSP served by an instance of WebLogic Server and display the results of that connection. It shows how to implement the following functions:
Listing 4-3 shows a sample SSLSocketClient. This code taken from the SSLSocketClient.java file located at SAMPLES_HOME\server\src\examples\security\sslclient.
Listing 4-3 SSLSocketClient Sample Code
package examples.security.sslclient;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.util.Hashtable;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import weblogic.security.SSL.HostnameVerifierJSSE;
import weblogic.security.SSL.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSession;
import weblogic.security.SSL.SSLSocketFactory;
import weblogic.security.SSL.TrustManagerJSSE;
/**
* A Java client demonstrates connecting to a JSP served by WebLogic Server
* using the secure port and displays the results of the connection.
*
* @author Copyright (c) 1999-2002 by BEA Systems, Inc. All Rights Reserved.
*/
public class SSLSocketClient {
public void SSLSocketClient() {}
public static void main (String [] argv)
throws IOException {
if ((argv.length < 2) || (argv.length > 3)) {
System.out.println("usage: java SSLSocketClient host sslport
<HostnameVerifierJSSE>");
System.out.println("example: java SSLSocketClient server2.weblogic.com 443
MyHVClassName");
System.exit(-1);
}
try {
System.out.println("\nhttps://" + argv[0] + ":" + argv[1]);
System.out.println(" Creating the SSLContext");
SSLContext sslCtx = SSLContext.getInstance("https");
File KeyStoreFile = new File ("mykeystore");
if (!KeyStoreFile.exists())
{
System.out.println("Keystore Error : mykeystore is not present in this
directory.");
System.out.println("To create it run - ant createmykeystore.");
System.exit(0);
}
System.out.println(" Initializing the SSLContext with client\n" +
" identity (certificates and private key),\n" +
" HostnameVerifierJSSE, AND NulledTrustManager");
// Open the keystore, retrieve the private key, and certificate chain
KeyStore ks = KeyStore.getInstance("jks");
ks.load(new FileInputStream("mykeystore"), null);
PrivateKey key = (PrivateKey)ks.getKey("mykey", "testkey".toCharArray());
Certificate [] certChain = ks.getCertificateChain("mykey");
sslCtx.loadLocalIdentity(certChain, key);
HostnameVerifierJSSE hVerifier = null;
if (argv.length < 3)
hVerifier = new NulledHostnameVerifier();
else
hVerifier = (HostnameVerifierJSSE) Class.forName(argv[2]).newInstance();
sslCtx.setHostnameVerifierJSSE(hVerifier);
TrustManagerJSSE tManager = new NulledTrustManager();
sslCtx.setTrustManagerJSSE(tManager);
System.out.println(" Creating new SSLSocketFactory with SSLContext");
SSLSocketFactory sslSF = (SSLSocketFactory) sslCtx.getSocketFactoryJSSE();
System.out.println(" Creating and opening new SSLSocket with
SSLSocketFactory");
// using createSocket(String hostname, int port)
SSLSocket sslSock = (SSLSocket) sslSF.createSocket(argv[0],
new Integer(argv[1]).intValue());
System.out.println(" SSLSocket created");
sslSock.addHandshakeCompletedListener(new MyListener());
OutputStream out = sslSock.getOutputStream();
// Send a simple HTTP request
String req = "GET /examplesWebApp/ShowDate.jsp HTTP/1.0\r\n\r\n";
out.write(req.getBytes());
// Retrieve the InputStream and read the HTTP result, displaying
// it on the console
InputStream in = sslSock.getInputStream();
byte buf[] = new byte[1024];
try
{
while (true)
{
int amt = in.read(buf);
if (amt == -1) break;
System.out.write(buf, 0, amt);
}
}
catch (IOException e)
{
return;
}
sslSock.close();
System.out.println(" SSLSocket closed");
} catch (Exception e) {
e.printStackTrace();
}
}
}
The SSLClientServlet sample is a simple servlet wrapper of the SSLClient sample.
Listing 4-4 shows a sample SSLClientServlet. This code taken from the SSLSClientServlet.java file located at SAMPLES_HOME\server\src\examples\security\sslclient.
Listing 4-4 SSLClientServlet Sample Code
package examples.security.sslclient;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;
/**
* SSLClientServlet is a simple servlet wrapper of
* examples.security.sslclient.SSLClient.
*
* @see SSLClient
* @author Copyright (c) 1999-2002 by BEA Systems, Inc. All Rights Reserved.
*/
public class SSLClientServlet extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.setHeader("Pragma", "no-cache"); // HTTP 1.0
response.setHeader("Cache-Control", "no-cache"); // HTTP 1.1
ServletOutputStream out = response.getOutputStream();
out.println("<br><h2>ssl client test</h2><br><hr>");
String[] target = request.getParameterValues("url");
try {
out.println("<h3>wls ssl client classes</h3><br>");
out.println("java SSLClient wls localhost 7001 7002
/examplesWebApp/SnoopServlet.jsp<br>");
out.println("<pre>");
SSLClient.wlsURLConnect("localhost", "7001", "7002",
"/examplesWebApp/SnoopServlet.jsp", out);
out.println("</pre><br><hr><br>");
} catch (IOException ioe) {
out.println("<br><pre> "+ioe.getMessage()+"</pre>");
ioe.printStackTrace();
}
}
}
Using Two-Way SSL Authentication
When using certificate authentication, WebLogic Server sends a digital certificate to the requesting client. The client examines the digital certificate to ensure that it is authentic, has not expired, and matches the WebLogic Server instance that presented it.
With two-way SSL authentication (a form of mutual authentication), the requesting client also presents a digital certificate to WebLogic Server. When the instance of WebLogic Server is configured for two-way SSL authentication, requesting clients are required to present digital certificates from a specified set of certificate authorities. WebLogic Server accepts only digital certificates that are signed by root certificates from the specified trusted certificate authorities.
For information on how to configure WebLogic Server for two-way SSL authentication, see the Configuring SSL in Managing WebLogic Security
The following sections describe the different ways two-way SSL authentication can be implemented in WebLogic Server.
Two-Way SSL Authentication with JNDI
When using JNDI for two-way SSL authentication in a Java client, use the setSSLClientCertificate() method of the WebLogic JNDI Environment class. This method sets a private key and chain of X.509 digital certificates for client authentication.
To pass digital certificates to JNDI, create an array of InputStreams opened on files containing DER-encoded digital certificates and set the array in the JNDI hash table. The first element in the array must contain an InputStream opened on the Java client's private key file. The second element must contain an InputStream opened on the Java client's digital certificate file. (This file contains the public key for the Java client.) Additional elements may contain the digital certificates of the root certificate authority and the signer of any digital certificates in a certificate chain. A certificate chain allows WebLogic Server to authenticate the digital certificate of the Java client if that digital certificate was not directly issued by a certificate authority registered for the Java client in the WebLogic Server keystore file.
You can use the weblogic.security.PEMInputStream class to read digital certificates stored in Privacy Enhanced Mail (PEM) files. This class provides a filter that decodes the base 64-encoded DER certificate into a PEM file.
Listing 4-5 demonstrates how to use two-way SSL authentication in a Java client.
Listing 4-5 Example of a Two-Way SSL Authentication Client That Uses JNDI
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import weblogic.jndi.Environment;
import weblogic.security.PEMInputStream;
import java.io.InputStream;
import java.io.FileInputStream;
public class SSLJNDIClient
{
public static void main(String[] args) throws Exception
{
Context context = null;
try {
Environment env = new Environment();
// set connection parameters
env.setProviderUrl("t3s://localhost:7002");
// The next two set methodes are optional if you are using
// a UserNameMapper interface.
env.setSecurityPrincipal("system");
env.setSecurityCredentials("weblogic");
InputStream key = new FileInputStream("certs/demokey.pem");
InputStream cert = new FileInputStream("certs/democert.pem");
// wrap input streams if key/cert are in pem files
key = new PEMInputStream(key);
cert = new PEMInputStream(cert);
env.setSSLClientCertificate(new InputStream[] { key, cert});
env.setInitialContextFactory(Environment.
DEFAULT_INITIAL_CONTEXT_FACTORY);
context = env.getInitialContext();
Object myEJB = (Object) context.lookup("myEJB");
}
finally {
if (context != null) context.close();
}
}
}
When the JNDI getInitialContext() method is called, the Java client and WebLogic Server execute mutual authentication in the same way that a Web browser performs mutual authentication to get a secure Web server connection. An exception is thrown if the digital certificates cannot be validated or if the Java client's digital certificate cannot be authenticated in the default (active) security realm. The authenticated user object is stored on the Java client's server thread and is used for checking the permissions governing the Java client's access to any protected WebLogic resources.
When you use the WebLogic JNDI Environment class, you must create a new Environment object for each call to the getInitialContext() method. Once you specify a User object and security credentials, both the user and their associated credentials remain set in the Environment object. If you try to reset them and then call the JNDI getInitialContext() method, the original user and credentials are used.
When you use two-way SSL authentication from a Java client, WebLogic Server gets a unique Java Virtual Machine (JVM) ID for each client JVM so that the connection between the Java client and WebLogic Server is constant. Unless the connection times out from lack of activity, it persists as long as the JVM for the Java client continues to execute. The only way a Java client can negotiate a new SSL connection reliably is by stopping its JVM and running another instance of the JVM.
The code in Listing 4-5 generates a call to the WebLogic Identity Assertion provider that implements the weblogic.security.providers.authentication.UserNameMapper interface. The class that implements the UserNameMapper interface returns a user object if the digital certificate is valid. WebLogic Server stores this authenticated user object on the Java client's thread in WebLogic Server and uses it for subsequent authorization requests when the thread attempts to use WebLogic resources protected by the default (active) security realm.
Note: The implementation of the weblogic.security.providers.authentication.UserNameMapper interface must be specified in your CLASSPATH.
If you have not configured an Identity Assertion provider that performs certificate-based authentication, a Java client running in a JVM with an SSL connection can change the WebLogic Server user identity by creating a new JNDI InitialContext and supplying a new user name and password in the JNDI SECURITY_PRINCIPAL and SECURITY_CREDENTIALS properties. Any digital certificates passed by the Java client after the SSL connection is made are not used. The new WebLogic Server user continues to use the SSL connection negotiated with the initial user's digital certificate.
If you have configured an Identity Assertion provider that performs certificate-based authentication, WebLogic Server passes the digital certificate from the Java client to the class that implements the UserNameMapper interface and the UserNameMapper class maps the digital certificate to a WebLogic Server user name. Therefore, if you want to set a new user identity when you use the certificate-based identity assertion, you cannot change the identity. This is because the digital certificate is processed only at the time of the first connection request from the JVM for each Environment.
Caution: Restriction: Multiple, concurrent, user logins to WebLogic Server from a single client JVM when using two-way SSL and JNDI is not supported. If multiple logins are executed on different threads, the results are undeterminable and might result in one user's requests being executed on another user's login, thereby allowing one user to access another user's data. WebLogic Server does not support multiple, concurrent, certificate-based logins from a single client JVM. For information on JNDI contexts and threads and how to avoid potential JNDI context problems, see "JNDI Contexts and Threads" and "How to Avoid JNDI Context Problems" in Programming WebLogic JNDI.
When using 2-way SSL, WebLogic Server verifies the digital certificate of the Web browser or Java client when establishing an SSL connection. However, the digital certificate does not identify the Web browser or Java client as a user in the WebLogic Server security realm. If the Web browser or Java client requests a WebLogic Server resource protected by a security policy, WebLogic Server requires the Web browser or Java client to have an identity. To handle this requirement, the WebLogic Identity Assertion provider allows you to enable a user name mapper that maps the digital certificate of a Web browser or Java client to a user in a WebLogic Server security realm. The user name mapper must be an implementation of the weblogic.security.providers.authentication.UserNameMapper interface.
The WebLogic Identity Assertion provider can call the implementation of the UserNameMapper interface for the following types of identity assertion token types:
If you need to map different types of certificates, you need write your own implementation of the UserNameMapper interface.
To implement a UserNameMapper interface that maps a digital certificate to a user name, write a UserNameMapper class that performs the following operations:
Using Two-Way SSL Authentication Between WebLogic Server Instances
You can use two-way SSL authentication in server-to-server communication in which one WebLogic Server instance is acting as the client of another WebLogic Server instance. Using two-way SSL authentication in server-to-server communication enables you to have dependable, highly-secure connections, even without the more common client/server environment.
Listing 4-6 shows an example of how to establish a secure connection from a servlet running in one instance of WebLogic Server to a second WebLogic Server instance called server2.weblogic.com.
Listing 4-6 Establishing a Secure Connection to Another WebLogic Server Instance
FileInputStream [] f = new FileInputStream[3];
f[0]= new FileInputStream("demokey.pem");
f[1]= new FileInputStream("democert.pem");
f[2]= new FileInputStream("ca.pem");
Environment e = new Environment ();
e.setProviderURL("t3s://server2.weblogic.com:443");
e.setSSLClientCertificate(f);
e.setSSLServerName("server2.weblogic.com");
e.setSSLRootCAFingerprints("ac45e2d1ce492252acc27ee5c345ef26");
e.setInitialContextFactory
("weblogic.jndi.WLInitialContextFactory");
Context ctx = new InitialContext(e.getProperties())
In Listing 4-6, the WebLogic JNDI Environment class creates a hash table to store the following parameters:
Note: For information on JNDI contexts and threads and how to avoid potential JNDI context problems, see "JNDI Contexts and Threads" and "How to Avoid JNDI Context Problems" in the Programming WebLogic JNDI.
Using Two-Way SSL Authentication with Servlets
To authenticate Java clients in a servlet (or any other server-side Java class), you must check whether the client presented a digital certificate and if so, whether the certificate was issued by a trusted certificate authority. The servlet developer is responsible for asking whether the Java client has a valid digital certificate. When developing servlets with the WebLogic Servlet API, you must access information about the SSL connection through the getAttribute() method of the HTTPServletRequest object.
The following attributes are supported in WebLogic Server servlets:
You have access to the user information defined in the digital certificates. When you get the javax.servlet.request.X509Certificate attribute, it is an array of the java.security.cert X.509 certificate. You simply cast the array to that and examine the certificates.
A digital certificate includes information, such as the following:
Using a Custom Host Name Verifier
A host name verifier validates that the host to which an SSL connection is made is the intended or authorized party. A host name verifier is useful when a WebLogic client or a WebLogic Server instance is acting as an SSL client to another application server. It helps prevent man-in-the-middle attacks.
By default, WebLogic Server, as a function of the SSL handshake, compares the common name in the Subject's Distinguished Name (SubjectDN) of the SSL server's digital certificate with the host name of the SSL server used to initiate the SSL connection. If these names do not match, the SSL connection is dropped.
The dropping of the SSL connection is caused by the SSL client, which validates the host name of the server against the digital certificate of the server. If anything but the default behavior is desired, you can either turn off host name verification or register a custom host name verifier. Turning off host name verification leaves the SSL connections vulnerable to man-in-the-middle attacks.
Note: Turn off host name verification when using the demonstration digital certificates shipped with WebLogic Server.
You can turn off host name verification in the following ways:
You can write a custom host name verifier. The weblogic.security.SSL.HostnameVerifierJSSE interface provides a callback mechanism so that you can define a policy for handling the case where the server name that is being connected to does not match the server name in the SubjectDN of the server's digital certificate.
To use a custom host name verifier, create a class that implements the weblogic.security.SSL.HostnameVerifierJSSE interface and define the methods that capture information about the server's security identity.
Note: This interface takes new style certificates and replaces the weblogic.security.SSL.HostnameVerifier interface, which is deprecated in this release of WebLogic Server.
Before you can use a custom host name verifier, you need to define the class for your implementation in the following ways:
An example of a custom host name verifier (see Listing 4-7) is available in the SSLclient code example located in the SAMPLES_HOME\server\src\examples\security\sslclient directory. This code example contains a NulledHostnameVerifier class which always returns true for the comparison. This sample allows the WebLogic SSL client to connect to any SSL server regardless of the server's host name and digital certificate SubjectDN comparison.
Listing 4-7 Host Name Verifier Sample Code
package examples.security.sslclient;
/**
* HostnameVerifierJSSE provides a callback mechanism so that
* implementers of this interface can supply a policy for handling
* the case where the host that's being connected to and the server
* name from the certificate SubjectDN must match.
*
* This is a null version of that class to show the WebLogic SSL
* client classes without major problems. For example, in this case,
* the client code connects to a server at 'localhost' but the
* democertificate's SubjectDN CommonName is 'bea.com' and the
* default WebLogic HostnameVerifierJSSE does a String.equals() on
* those two hostnames.
*
* @see HostnameVerifier#verify
* @author Copyright (c) 1999-2002 by BEA Systems, Inc. All Rights
* Reserved.
*/
public class NulledHostnameVerifier implements
weblogic.security.SSL.HostnameVerifierJSSE {
public boolean verify(String urlHostname, String certHostname) {
return true;
}
}
The weblogic.security.SSL.TrustManagerJSSE interface allows you to override validation errors in a peer's digital certificate and continue the SSL handshake. You can also use the interface to discontinue an SSL handshake by performing additional validation on a server's digital certificate chain.
Note: This interface takes new style certificates and replaces the weblogic.security.SSL.TrustManager interface, which is deprecated in this release of WebLogic Server.
When an SSL client connects to an instance of WebLogic Server, the server presents its digital certificate chain to the client for authentication. That chain could contain an invalid digital certificate. The SSL specification says that the client should drop the SSL connection upon discovery of an invalid certificate. Web browsers, however, ask the user whether to ignore the invalid certificate and continue up the chain to determine if it is possible to authenticate the SSL server with any of the remaining certificates in the certificate chain. You can use the TrustManagerJSSE interface to eliminate this inconsistent practice by controlling when to continue or discontinue an SSL connection. Using a trust manager, you can perform custom checks before continuing an SSL connection. For example, you can use a trust manager to specify that only users from specific localities, such as towns, states, or countries, or users with other special attributes, are allowed to gain access via the SSL connection.
Use the weblogic.security.SSL.TrustManagerJSSE interface to create a trust manager. The interface contains a set of error codes for certificate verification. You can also perform additional validation on the peer certificate and interrupt the SSL handshake if need be. After a digital certificate has been verified, the weblogic.security.SSL.TrustManagerJSSE interface uses a callback function to override the result of verifying the digital certificate. You can associate an instance of a trust manager with an SSL context through the setTrustManagerJSSE() method.
The weblogic.security.SSL.TrustManagerJSSE interface conforms to the JSSE specification. You can only set up a trust manger programmatically; its use cannot be defined through the Administration Console or on the command-line.
Note: Depending on the checks performed, use of a trust manager may potentially impact performance.
An example of a trust manager (see Listing 4-8) is available in the SSLClient code example located in the SAMPLES_HOME\server\src\examples\security\sslclient directory.
Listing 4-8 TrustManager Code Example
package examples.security.sslclient;
import weblogic.security.SSL.TrustManagerJSSE;
import javax.security.cert.X509Certificate;
public class NulledTrustManagerJSSE implements TrustManagerJSSE{
public boolean certificateCallback(X509Certificate[] o, int validateErr) {
System.out.println(" --- Do Not Use In Production ---\n" + " By using this " +
"NulledTrustManager, the trust in the server's identity "+
"is completely lost.\n --------------------------------");
for (int i=0; i<o.length; i++)
System.out.println(" certificate " + i + " -- " + o[i].toString());
return true;
}
}
The SSLSocketClient example uses the custom trust manager shown above. The SSLSocketClient shows how to set up a new SSL connection by using an SSL context with the trust manager. This example is also located in the SAMPLES_HOME\server\src\examples\security\sslclient directory.
Using a Handshake Completed Listener
The javax.net.ssl.HandshakeCompletedListener interface defines how the SSL client receives notifications about the completion of an SSL handshake on a given SSL connection. It also defines the number of times an SSL handshake takes place on a given SSL connection. Listing 4-9 shows a code example of a HandshakeCompletedListener interface. This example is also located in the SAMPLES_HOME\server\src\examples\security\sslclient directory.
Listing 4-9 HandshakeCompletedListener Code Example
package examples.security.sslclient;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.util.Hashtable;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLSession;
public class MyListener implements HandshakeCompletedListener
{
public void handshakeCompleted(javax.net.ssl.
HandshakeCompletedEvent event)
{
SSLSession session = event.getSession();
System.out.println("Handshake Completed with peer " +
session.getPeerHost());
System.out.println(" cipher: " + session.getCipherSuite());
javax.security.cert.X509Certificate[] certs = null;
try
{
certs = session.getPeerCertificateChain();
}
catch (javax.net.ssl.SSLPeerUnverifiedException puv)
{
certs = null;
}
if (certs != null)
{
System.out.println(" peer certificates:");
for (int z=0; z<certs.length; z++) System.out.
println("certs["+z+"]: " + certs[z]);
}
else
{
System.out.println("No peer certificates presented");
}
}
}
The SSLContext class is used to programmatically configure SSL and retain SSL session information. For example, all sockets that are created by socket factories provided by the SSLContext class can agree on session state by using the handshake protocol associated with the SSL context. Each instance can be configured with the keys, certificate chains, and trusted root certificate authorities that it needs to perform authentication. These sessions are cached so that other sockets created under the same SSL context can potentially reuse them later. For more information on session caching see SSL Session Behavior in Managing WebLogic Security. To associate an instance of a trust manager class with its SSL context, use the weblogic.security.SSL.SSLContext.setTrustManagerJSSE() method.
You can only set up an SSL context programmatically; not by using the Administration Console or the command line. A Java new expression or the getInstance() method of the SSLContext class can create an SSLContext object. The getInstance() method is static and it generates a new SSLContext object that implements the specified secure socket protocol. An example of using the SSLContext class is provided in the SSLSocketClient sample in the SAMPLES_HOME\server\src\examples\security\sslclient directory. This example (see Listing 4-3) shows how to create a new SSL socket factory that will create a new SSL socket using SSLContext.
Listing 4-10 shows a sample instantiation using the getInstance() method.
Listing 4-10 SSL Context Code Example
import weblogic.security.SSL.SSLContext;
SSLcontext sslctx = SSLContext.getInstance ("https")
Using an SSL Server Socket Factory
Instances of the SSLServerSocketFactory class create and return SSL sockets. This class extends javax.net.SocketFactory.
Listing 4-11 shows a sample instantiation of this class. Listing 4-3 shows a code example that uses the SSLServerSocketFactory class. This code example is taken from the SSLSocketClient.java file located at SAMPLES_HOME\server\src\examples\security\sslclient.
Listing 4-11 SSLServerSocketFactory Code Example
import weblogic.security.SSL.SSLSocketFactory;
SSLSocketFactory sslSF = (SSLSocketFactory) sslCtx.getSocketFactoryJSSE();
Using URLs to Make Outbound SSL Connections
You can use a URL object to make an outbound SSL connection from a WebLogic Server instance acting as a client to another WebLogic Server instance. WebLogic Server supports both one-way and two-way SSL authentication for outbound SSL connections.
For one-way SSL authentication, you use the java.net.URL, java.net.URLConnection, and java.net.HTTPURLConnection classes to make outbound SSL connections using URL objects. Listing 4-12 shows a simpleURL class that supports both HTTP and HTTPS URLs and that only uses these Java classes (that is, no WebLogic classes are required). To use the simpleURL class for one-way SSL authentication (HTTPS) on WebLogic Server, all that is required is that "weblogic.net" be defined in the system property for java.protocols.handler.pkgs.
Note: Because the simpleURL sample shown in Listing 4-12 defaults trust and hostname checking, this sample requires that you connect to a real Web server that is trusted and that passes hostname checking by default. Otherwise, you must override trust and hostname checking on the command line.
Listing 4-12 One-Way SSL Authentication URL Outbound SSL Connection Class That Uses Java Classes Only
import java.net.URL;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import java.io.IOException;
public class simpleURL
{
public static void main (String [] argv)
{
if (argv.length != 1)
{
System.out.println("Please provide a URL to connect to");
System.exit(-1);
}
setupHandler();
connectToURL(argv[0]);
}
private static void setupHandler()
{
java.util.Properties p = System.getProperties();
String s = p.getProperty("java.protocol.handler.pkgs");
if (s == null)
s = "weblogic.net";
else if (s.indexOf("weblogic.net") == -1)
s += "|weblogic.net";
p.put("java.protocol.handler.pkgs", s);
System.setProperties(p);
}
private static void connectToURL(String theURLSpec)
{
try
{
URL theURL = new URL(theURLSpec);
URLConnection urlConnection = theURL.openConnection();
HttpURLConnection connection = null;
if (!(urlConnection instanceof HttpURLConnection))
{
System.out.println("The URL is not using HTTP/HTTPS: " +
theURLSpec);
return;
}
connection = (HttpURLConnection) urlConnection;
connection.connect();
String responseStr = "\t\t" +
connection.getResponseCode() + " -- " +
connection.getResponseMessage() + "\n\t\t" +
connection.getContent().getClass().getName() + "\n";
connection.disconnect();
System.out.println(responseStr);
}
catch (IOException ioe)
{
System.out.println("Failure processing URL: " + theURLSpec);
ioe.printStackTrace();
}
}
}
For two-way SSL authentication, the weblogic.net.http.HttpsURLConnection class provides a way to specify the security context information for a client, including the digital certificate and private key of the client. Instances of this class represent an HTTPS connection to a remote object.
The SSLClient code example demonstrates using the WebLogic URL object to make an outbound SSL connection (see Listing 4-13). The code example shown in Listing 4-13 is excerpted from the SSLClient.java file in the SAMPLES_HOME\server\src\examples\security\sslclient directory.
Listing 4-13 WebLogic Two-Way SSL Authentication URL Outbound SSL Connection Code Example
wlsUrl = new URL("https", host, Integer.valueOf(sport).intValue(),
query);
weblogic.net.http.HttpsURLConnection sconnection =
new weblogic.net.http.HttpsURLConnection(wlsUrl);
InputStream [] ins = new InputStream[2];
ins[0] = new FileInputStream("client2certs.pem");
ins[1] = new FileInputStream("clientkey.pem");
String pwd = "clientkey";
sconnection.loadLocalIdentity(ins[0], ins[1],
pwd.toCharArray());
A complete working SSL authentication sample is provided with the WebLogic Server product. The sample is located in the SAMPLES_HOME\server\src\examples\security\sslclient directory. For a description of the sample and instructions on how to build, configure, and run this sample, see the package.html file in the sample directory. You can modify this code example and reuse it.
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |