3 Configuring Transport-Level Security
Transport-level security refers to securing the connection between a client application and a web service with Secure Sockets Layer (SSL).
SSL provides secure connections by allowing two applications connecting over a network to authenticate the other's identity and by encrypting the data exchanged between the applications. Authentication allows a server, and optionally a client, to verify the identity of the application on the other end of a network connection. A client certificate (two-way SSL) can be used to authenticate the user.
See Secure Sockets Layer (SSL) in Understanding Security for Oracle WebLogic Server for general information about SSL and the implementations included in WebLogic Server.
WebLogic Server provides transport-level policies that use HTTPS to protect the connection and can additionally require an authentication mechanism such as HTTP Basic authentication. HTTP Basic authentication does not encrypt credentials. Use it only over HTTPS.
This chapter includes the following sections:
Configuring Transport-Level Security Through Policy
WebLogic Server includes the predefined transport-level policy files described in Available Transport-Level Policies, which typically satisfy the security needs of most programmers and use cases.
You can also create and use your own WS-SecurityPolicy file if you need additional configuration, as described in Creating and Using a Custom Policy File. If you need to do this, you can use the predefined WS-SecurityPolicy files as templates to create your own custom files. The predefined policy files are located in ORACLE_HOME/oracle_common/modules/com.oracle.webservices.wls.wls-soap-stack-impl.jar. Within that archive, they are under /weblogic/wsee/policy/runtime.
For example, the Oracle-supplied Wssp1.2-2007-Saml2.0-Bearer-Https.xml policy file includes the following assertion indicating that the policy requires one-way SSL, as shown here.
Example 3-1 Specifying SSL in a Policy
<sp:TransportToken> <wsp:Policy> <sp:HttpsToken/> </wsp:Policy> </sp:TransportToken>
If you needed to instead use two-way SSL, you could create a custom policy that adds the RequireClientCertificate assertion, as shown below.
Example 3-2 Two-Way SSL in a Policy
<sp:TransportToken> <wsp:Policy> <sp:HttpsToken > <wsp:Policy> <sp:RequireClientCertificate/> </wsp:Policy> </sp:HttpsToken> </wsp:Policy> </sp:TransportToken>
The Wssp1.2-2007-Https-BasicAuth.xml policy file requires both SSL and HTTP BASIC Authentication, as shown below.
Example 3-3 SSL and HTTP Basic Authentication in a Policy
<sp:TransportToken> <wsp:Policy> <sp:HttpsToken> <wsp:Policy> <sp:HttpBasicAuthentication/> </wsp:Policy> </sp:HttpsToken> </wsp:Policy> </sp:TransportToken>
Available Transport-Level Policies
These policies require use of the https protocol to access the WSDL and invoke web services operations:
Table 3-1 Transport Level Policies
| Policy File | Description |
|---|---|
|
|
One-way SSL uses SAML 2.0 token with Bearer confirmation method for Authentication. |
|
|
Same as |
|
|
One way SSL. |
|
W |
One way SSL with Basic Authentication. A 401 challenge occurs if the Authorization header is not present in the request. |
|
|
Two way SSL. The recipient checks for the initiator's public certificate. Note that the client certificate can be used for authentication. Set Two Way Client Cert Behavior to Client Certs Requested But Not Enforced. See Set Up TLS in Oracle WebLogic Remote Console Online Help . |
|
|
One way SSL with digest Username Token. |
|
|
One way SSL with plain text Username Token. |
|
|
Same as |
|
|
One way SSL. |
|
|
One way SSL with Basic Authentication. A 401 challenge occurs if the Authorization header is not present in the request. |
|
|
One way SSL with digest Username Token. |
|
|
One way SSL with plain text Username Token. |
|
|
Two way SSL. The recipient checks for the initiator's public certificate. Note that the client certificate can be used for authentication. |
Prerequisite: Configure SSL
Before you can use a transport-level policy to protect a web service, you must configure SSL for the core WebLogic Server security subsystem.
The out-of-the-box private key and X.509 certificate pairs are provided for demonstration and testing purposes. For this reason Oracle highly recommends you use your own keystore and key pair in production.
You can configure one-way SSL where WebLogic Server is required to present a certificate to the client application, or two-way SSL where both the client applications and WebLogic Server present certificates to each other.
To configure two-way or one-way SSL for the core WebLogic Server security subsystem, see Configuring SSL in Administering Security for Oracle WebLogic Server.
If you configure two-way SSL for WebLogic Server, you must also configure SSL for the client application, as described in Configuring Two-Way SSL for a Client Application.
Configuring SSL: Main Steps
This section summarizes the procedure described in Setting Up SSL: Main Steps. The steps are described here for your convenience; see Setting Up SSL: Main Steps for complete information.
To set up SSL:
-
Configure identity and trust, as described in Configuring Keystores:
-
Obtain digital certificates, private keys, and trusted CA certificates from the CertGen utility, the keytool utility, or a reputable vendor such as Entrust or Verisign. You can also use the digital certificates, private keys, and trusted CA certificates provided by the WebLogic Server kit. The demonstration digital certificates, private keys, and trusted CA certificates should be used in a development environment only.
-
Store the private keys, digital certificates, and trusted CA certificates. Private keys and trusted CA certificates are stored in a keystore.
-
Configure the identity and trust keystores for WebLogic Server in WebLogic Remote Console. See Configure Keystores in Oracle WebLogic Remote Console Online Help.
-
-
Set SSL configuration options for the private key alias and password in WebLogic Remote Console.
Optionally, set configuration options that require the presentation of client certificates (for two-way SSL). See Set Up TLS in Oracle WebLogic Remote Console Online Help.
Configuring Two-Way SSL for a Client Application
Note:
web services using asynchronous or reliable messaging will automatically use the server's SSL certificate when establishing a new connection (back from the receiving service to the sending service) for the purposes of sending asynchronous responses, acknowledgments, and so forth.
If you configured two-way SSL for WebLogic Server, the client application must present a certificate to WebLogic Server, in addition to WebLogic Server presenting a certificate to the client application as required by one-way SSL. You must also follow these requirements:
-
Create a client-side keystore that contains the client's private key and X.509 certificate pair.
The SSL package of Java SE requires that the password of the client's private key must be the same as the password of the client's keystore. A Java keystore can contain multiple private-key and certificate-chain entries, each identified by an alias. When
SSLClientUtil.getSSLSocketFactoryFromSysProperties()initializes the default key manager, it supplies thejavax.net.ssl.keyStorePasswordvalue as the recovery password for the keystore’s private-key entries. Ensure the selected entries are recoverable with that value. To select a specific client identity and, when needed, supply its key password, createPersistentSSLInfoand callsetKeyAliasandsetKeyPasswordas shown in Example 3-9. -
Configure the core WebLogic Server's security subsystem, mapping the client's X.509 certificate in the client keystore to a user. See Configuring a User Name Mapper in Administering Security for Oracle WebLogic Server.
-
Create a truststore which contains the certificates that the client trusts; the client application uses this truststore to validate the certificate it receives from WebLogic Server. A separate truststore is optional but can simplify access control and lifecycle management by separating trusted certificates from the client’s private-key material.
You can use the CertGen utility or the keytool utility to perform this step. For development purposes, the
keytoolutility is the easiest way to get started. See Keytool in JDK Tool Specifications.See Obtaining Private Keys, Digital Certificates, and Trusted Certificate Authorities in Administering Security for Oracle WebLogic Server.
-
Set Two Way Client Cert Behavior to "Client Certs Requested But Not Enforced." See Set Up TLS in Oracle WebLogic Remote Console Online Help.
-
When you run the client application that invokes the web service, specify the following properties:
-
-Djavax.net.ssl.trustStore=trustStore
-
-Djavax.net.ssl.trustStorePassword=trustStorePassword
where trustStore specifies the name of the client-side truststore that contains the list of trusted certificates (one of which should be the server's certificate) and trustStorePassword specifies the truststore's password.
The preceding properties are in addition to the standard properties you must set to specify the client-side keystore:
-
-Djavax.net.ssl.keyStore=keyStore
-
-Djavax.net.ssl.keyStorePassword=keyStorePassword
-
Configuring Transport-Level Security Through Policy: Main Steps
To configure transport-level web services security via one or more policy files:
Example of Configuring Transport Security for JAX-WS
This section describes a simple example for configuring JAX-WS with Transport Security from a standalone client for one-way SSL.
See the following documentation for additional prerequisite information:
-
Configuring SSL in Administering Security for Oracle WebLogic Server
-
Set Up TLS in Oracle WebLogic Remote Console Online Help
-
Configure Keystores in Oracle WebLogic Remote Console Online Help
One-Way SSL (HTTPS and HTTP Basic Authentication Example)
This example uses HTTPS to protect the connection and HTTP Basic authentication to authenticate the caller. The service and both client variants use urn:examples:https, HttpsBasicAuthService, HttpsBasicAuthPort, and the echoString operation. The WebLogic and JDK clients differ only in HTTPS handler and truststore configuration. Neither client installs a certificate or hostname verification bypass.
Save the following files together in an empty example directory: HttpsBasicAuth.java, HttpsBasicAuthWlsClient.java, HttpsBasicAuthJdkClient.java, and build.xml. Use JDK 25 and the Ant installation supplied with WebLogic Server. Set WL_HOME to the installation's wlserver directory.
Prepare a disposable domain with an Administration Server named AdminServer, an enabled SSL listen port, and an identity certificate whose subject alternative name matches the HTTPS endpoint. Create a PKCS12 client truststore containing its trusted certificate or issuing CA. Keep the private identity key in the server's identity keystore; do not distribute it with the client truststore. Create a user for HTTP Basic authentication and protected WLST user configuration/key files for deployment. Use the configuration procedures earlier in this chapter to prepare the domain; these examples do not create or reconfigure it.
Build with ant build. The build generates the service WSDL and both clients' service classes from that WSDL. Run each client in a fresh JVM so protocol-handler selection is unambiguous.
Note:
If you specify a transport-level security policy for your web service, it must be at the class level.
In addition, the transport-level security policy must apply to both the inbound and outbound directions. That is, you cannot have HTTPS for inbound and HTTP for outbound.
Example 3-4 Web Service One-Way SSL Example
package examples.https;
import jakarta.jws.WebMethod;
import jakarta.jws.WebService;
import weblogic.jws.Policy;
@WebService(name = "HttpsBasicAuth", serviceName = "HttpsBasicAuthService",
portName = "HttpsBasicAuthPort", targetNamespace = "urn:examples:https")
@Policy(uri = "policy:Wssp1.2-2007-Https-BasicAuth.xml")
public class HttpsBasicAuth {
@WebMethod
public String echoString(String input) {
return "Echo: " + input;
}
}
The standalone Java web service client code that uses "weblogic.net" as the Java protocol handler is shown in Example 3-5:
Example 3-5 Web Service Client One-Way SSL Example With weblogic.net
package examples.https;
import java.io.Console;
import java.net.URI;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import javax.xml.namespace.QName;
import jakarta.xml.ws.BindingProvider;
import examples.https.generated.HttpsBasicAuthService;
public final class HttpsBasicAuthWlsClient {
public static void main(String[] args) throws Exception {
if (args.length != 4) {
throw new IllegalArgumentException(
"Usage: HttpsBasicAuthWlsClient <local-wsdl> <https-endpoint> <username> <truststore.p12>");
}
Console console = System.console();
if (console == null) {
throw new IllegalStateException("Run in a terminal with a non-echoing console");
}
char[] storePassword = console.readPassword("Truststore password: ");
char[] password = console.readPassword("HTTP Basic password: ");
if (storePassword == null || password == null) {
throw new IllegalStateException("Credential input was cancelled");
}
try {
invoke(args[0], args[1], args[2], args[3], storePassword, password);
} finally {
Arrays.fill(storePassword, '\0');
Arrays.fill(password, '\0');
}
}
public static void invoke(String wsdl, String endpoint, String user,
String trustStore, char[] storePassword, char[] password) throws Exception {
URI address = URI.create(endpoint);
if (!"https".equalsIgnoreCase(address.getScheme()) || address.getHost() == null) {
throw new IllegalArgumentException("An absolute HTTPS endpoint is required");
}
System.setProperty("java.protocol.handler.pkgs", "weblogic.net");
System.setProperty("weblogic.security.TrustKeyStore", "CustomTrust");
System.setProperty("weblogic.security.CustomTrustKeyStoreFileName", trustStore);
System.setProperty("weblogic.security.CustomTrustKeyStoreType", "PKCS12");
System.setProperty("weblogic.security.CustomTrustKeyStorePassPhrase", new String(storePassword));
HttpsBasicAuthService service = new HttpsBasicAuthService(
Path.of(wsdl).toUri().toURL(),
new QName("urn:examples:https", "HttpsBasicAuthService"));
var port = service.getHttpsBasicAuthPort();
Map<String, Object> context = ((BindingProvider) port).getRequestContext();
context.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
context.put(BindingProvider.USERNAME_PROPERTY, user);
context.put(BindingProvider.PASSWORD_PROPERTY, new String(password));
try {
System.out.println(port.echoString("documentation review"));
} finally {
context.remove(BindingProvider.PASSWORD_PROPERTY);
}
}
}
The standalone Java web service client code that uses the default Java protocol handler is shown in Example 3-6:
Example 3-6 Web Service Client One-Way SSL Example With java.net
package examples.https;
import java.io.Console;
import java.net.URI;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Map;
import javax.xml.namespace.QName;
import jakarta.xml.ws.BindingProvider;
import examples.https.generated.HttpsBasicAuthService;
public final class HttpsBasicAuthJdkClient {
public static void main(String[] args) throws Exception {
if (args.length != 4) {
throw new IllegalArgumentException(
"Usage: HttpsBasicAuthJdkClient <local-wsdl> <https-endpoint> <username> <truststore.p12>");
}
Console console = System.console();
if (console == null) {
throw new IllegalStateException("Run in a terminal with a non-echoing console");
}
char[] storePassword = console.readPassword("Truststore password: ");
char[] password = console.readPassword("HTTP Basic password: ");
if (storePassword == null || password == null) {
throw new IllegalStateException("Credential input was cancelled");
}
try {
invoke(args[0], args[1], args[2], args[3], storePassword, password);
} finally {
Arrays.fill(storePassword, '\0');
Arrays.fill(password, '\0');
}
}
public static void invoke(String wsdl, String endpoint, String user,
String trustStore, char[] storePassword, char[] password) throws Exception {
URI address = URI.create(endpoint);
if (!"https".equalsIgnoreCase(address.getScheme()) || address.getHost() == null) {
throw new IllegalArgumentException("An absolute HTTPS endpoint is required");
}
System.setProperty("javax.net.ssl.trustStore", trustStore);
System.setProperty("javax.net.ssl.trustStoreType", "PKCS12");
System.setProperty("javax.net.ssl.trustStorePassword", new String(storePassword));
HttpsBasicAuthService service = new HttpsBasicAuthService(
Path.of(wsdl).toUri().toURL(),
new QName("urn:examples:https", "HttpsBasicAuthService"));
var port = service.getHttpsBasicAuthPort();
Map<String, Object> context = ((BindingProvider) port).getRequestContext();
context.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
context.put(BindingProvider.USERNAME_PROPERTY, user);
context.put(BindingProvider.PASSWORD_PROPERTY, new String(password));
try {
System.out.println(port.echoString("documentation review"));
} finally {
context.remove(BindingProvider.PASSWORD_PROPERTY);
}
}
}
The related portion of the ant build file is shown in Example 3-7:
Example 3-7 Ant Build File
<?xml version="1.0" encoding="UTF-8"?>
<project name="doc-https-basic" default="build" basedir=".">
<property environment="env"/>
<fail unless="env.WL_HOME" message="Set WL_HOME to the wlserver directory in your WebLogic installation."/>
<path id="wls.classpath"><pathelement location="${env.WL_HOME}/server/lib/weblogic.jar"/></path>
<taskdef name="jwsc" classname="weblogic.wsee.tools.anttasks.JwscTask" classpathref="wls.classpath"/>
<taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" classpathref="wls.classpath"/>
<target name="service">
<mkdir dir="build/service"/>
<jwsc srcdir="." destdir="build/service" fork="true" keepGenerated="true">
<classpath refid="wls.classpath"/>
<jws file="HttpsBasicAuth.java" type="JAXWS" generateWsdl="true" explode="true">
<WLHttpTransport contextPath="doc-https" serviceUri="HttpsBasicAuth"/>
</jws>
</jwsc>
</target>
<target name="generate" depends="service">
<mkdir dir="build/generated"/>
<clientgen type="JAXWS" wsdl="build/service/HttpsBasicAuth/WEB-INF/HttpsBasicAuthService.wsdl"
destDir="build/generated" packageName="examples.https.generated"/>
</target>
<target name="build" depends="generate">
<mkdir dir="build/classes"/>
<javac srcdir="." destdir="build/classes" includeantruntime="false"
includes="HttpsBasicAuthWlsClient.java,HttpsBasicAuthJdkClient.java,build/generated/**/*.java">
<classpath refid="wls.classpath"/>
</javac>
<copy todir="build/classes"><fileset dir="build/generated" excludes="**/*.java,**/*.class"/></copy>
</target>
<target name="clean"><delete dir="build"/></target>
</project>
Deploy, Invoke, and Clean Up
Save the following complete helper as deploy_https.py. Start WLST from the example directory. Pass deploy or undeploy, the protected user configuration/key filenames, a t3s administration URL, and the PKCS12 administration truststore. The script prompts for the truststore password.
# Start WLST in a terminal. The truststore password is read without echo.
import sys
from java.lang import System
from java.io import File
if len(sys.argv) != 6:
raise ValueError('Usage: deploy_https.py <deploy|undeploy> <user-config> <user-key> <t3s-admin-url> <truststore.p12>')
action, config, key, admin_url, truststore = sys.argv[1:6]
if action not in ['deploy', 'undeploy'] or not admin_url.startswith('t3s://'):
raise ValueError('Select deploy or undeploy and a t3s Administration Server URL')
console = System.console()
if console is None:
raise ValueError('Run WLST in a terminal with a non-echoing console')
console.writer().print('Truststore password: ')
console.writer().flush()
password = console.readPassword()
if password is None:
raise ValueError('Credential input was cancelled')
from java.lang import String
from java.util import Arrays
try:
System.setProperty('weblogic.security.TrustKeyStore', 'CustomTrust')
System.setProperty('weblogic.security.CustomTrustKeyStoreFileName', truststore)
System.setProperty('weblogic.security.CustomTrustKeyStoreType', 'PKCS12')
System.setProperty('weblogic.security.CustomTrustKeyStorePassPhrase', String(password))
finally:
for i in range(len(password)):
password[i] = '\0'
connect(userConfigFile=config, userKeyFile=key, url=admin_url)
try:
if action == 'deploy':
deploy('doc-https-basic', File('build/service').getCanonicalPath(),
targets='AdminServer', block='true')
else:
undeploy('doc-https-basic', block='true')
finally:
disconnect()
The commands below use these shell variables: WLST is the installation's oracle_common/common/bin/wlst.sh; USER_CONFIG and USER_KEY are protected WLST credential files; ADMIN_URL is the secure administration URL; ADMIN_TRUST and CLIENT_TRUST are PKCS12 truststore filenames; ENDPOINT is the deployed HTTPS URL ending in /doc-https/HttpsBasicAuth; and BASIC_USER is the application user. None of these variables contains a password. Use the corresponding classpath separator on Windows.
ant build "$WLST" deploy_https.py deploy "$USER_CONFIG" "$USER_KEY" "$ADMIN_URL" "$ADMIN_TRUST" WSDL=build/service/HttpsBasicAuth/WEB-INF/HttpsBasicAuthService.wsdl CP="build/classes:$WL_HOME/server/lib/weblogic.jar" java -cp "$CP" examples.https.HttpsBasicAuthWlsClient "$WSDL" "$ENDPOINT" "$BASIC_USER" "$CLIENT_TRUST" java -cp "$CP" examples.https.HttpsBasicAuthJdkClient "$WSDL" "$ENDPOINT" "$BASIC_USER" "$CLIENT_TRUST" "$WLST" deploy_https.py undeploy "$USER_CONFIG" "$USER_KEY" "$ADMIN_URL" "$ADMIN_TRUST" ant clean
Each client prompts for the truststore password and the HTTP Basic password without echo. A successful invocation prints Echo: documentation review. An incorrect password must produce an authentication failure. An untrusted certificate or an endpoint hostname that does not match the certificate must produce a TLS identity-check failure. Correct the credentials, certificate, or endpoint; do not bypass the checks. Test the actual deployment hostname because some WebLogic client paths have special handling for local names.
Persisting the State of a Request over SSL
Oracle WebLogic Server includes a two-way SSL client API for JAX-WS that you can use to construct an SSLSocketFactory from system properties or from a new weblogic.wsee.jaxws.sslclient.PersistentSSLInfo class. The API can persist SSL info for Reliable Messaging, callbacks, and so forth.
Note:
weblogic.wsee.client.ssl.relaxedtrustmanager and weblogic.security.SSL.ignoreHostnameVerification disable server-identity checks. Do not use them in production examples or deployment instructions. If Oracle Support requires one temporarily for diagnosis, restrict it to an isolated test process and remove it immediately after the diagnostic run.
The following classes are available. See the Javadoc for complete descriptions.
-
weblogic.wsee.jaxws.sslclient.SSLClientUtil. This class has the following methods:
-
public static SSLSocketFactory getSSLSocketFactory(KeyManager[] kms, TrustManager[] tms);
-
public static SSLSocketFactory getSSLSocketFactory(PersistentSSLInfo sslInfo);
-
public static SSLSocketFactory getSSLSocketFactoryFromSysProperties();
-
-
weblogic.wsee.jaxws.sslclient.PersistentSSLInfo, a Javabean for setting SSL info.
-
weblogic.wsee.jaxws.JAXWSProperties, includes a CLIENT_PERSISTENT_SSL_INFO property.
Example of Getting SSLSocketFactory From System Properties
Example 3-8 shows an example of getting the SSLSocketFactory from system properties and using them in the request context.
Note:
A Java keystore can contain multiple private-key and certificate-chain entries, each identified by an alias. When SSLClientUtil.getSSLSocketFactoryFromSysProperties() initializes the default key manager, it supplies the javax.net.ssl.keyStorePassword value as the recovery password for the keystore’s private key entries. Ensure the selected entries are recoverable with that value. To select a specific client identity and, when needed, supply its key password, create PersistentSSLInfo and call setKeyAlias and setKeyPassword as shown in Example 3-9.
Example 3-8 Getting SSLSocketFactory From System Properties
String clientKeyStore = ...;
String clientKeyStorePasswd = ...;
String trustKeystore = ...;
String trustKeystorePasswd = ...;
System.setProperty("javax.net.ssl.keyStore", clientKeyStore);
System.setProperty("javax.net.ssl.keyStorePassword", clientKeyStorePasswd);
System.setProperty("javax.net.ssl.trustStore", trustKeystore);
System.setProperty("javax.net.ssl.trustStorePassword", trustKeystorePasswd);
((BindingProvider) port).getRequestContext().put(
JAXWSProperties.SSL_SOCKET_FACTORY,
SSLClientUtil.getSSLSocketFactoryFromSysProperties());
Example 3-9 shows an example of getting SSLSocketFactory from persistent info (PersistentSSLInfo), as well as directly setting a SSLSocketFactory if persistence is not needed.
Example 3-9 Getting SSLSocketFactory from PersistentSSLInfo
String clientKeyStore = ...;
String clientKeyStorePasswd = ...;
String clientKeyAlias = ...;
String clientKeyPass = ...;
String trustKeystore = ...;
String trustKeystorePasswd = ...;
PersistentSSLInfo sslInfo = new PersistentSSLInfo();
sslInfo.setKeystore(clientKeyStore);
sslInfo.setKeystorePassword(clientKeyStorePasswd);
sslInfo.setKeyAlias(clientKeyAlias);
sslInfo.setKeyPassword(clientKeyPass);
sslInfo.setTrustKeystore(trustKeystore);
//user can print out the sslInfo for debug
System.out.print(sslInfo.toString());
//Put sslInfo into requestContext for persistence, it might be required by JAX-WS
advance features, such as, RM, Callback
((BindingProvider) port).getRequestContext().put(
JAXWSProperties.CLIENT_PERSISTENT_SSL_INFO, sslInfo);
//Alternatively, you can directly set a SSLSocketFactory if persistence is
not necessary. Note: The following line should be omitted if sslInfo is set with
above line.
((BindingProvider) port).getRequestContext().put(
JAXWSProperties.SSL_SOCKET_FACTORY,
SSLClientUtil.getSSLSocketFactory(sslInfo));
sslInfo can set a key alias (clientKeyAlias) that points to a key in keystore (as an SSL client-side key) in the event that the client keystore has multiple keys.