![]() |
|||
![]() |
![]() ![]() |
![]() |
![]() ![]() |
![]() |
![]() ![]() |
![]() |
| |||||
As shown in Example 11-10 above, the client end of the private connection is created using a very similar set of properties as the server end. However, the client end of the connector supplies the user and password information via a different callback handler, DigestMD5ClientCallbackHandler. Like DigestMD5ServerCallbackHandler, DigestMD5ClientCallbackHandler is an implementation of the CallbackHandler interface. DigestMD5ClientCallbackHandler is passed the username and password expected by DigestMD5ServerCallbackHandler when it is instantiated, which it then passes to the DIGEST-MD5 client mechanism. The client DIGEST-MD5 mechanism then makes them available for comparison with the properties held by the server, thus allowing the connection to the MBean server to be established. Operations can then be performed on the MBeans the MBean server contains.
|
$ javac -classpath classpath \ mbeans/SimpleStandard.java \ mbeans/SimpleStandardMBean.java \ server/Server.java \ server/DigestMD5ServerCallbackHandler.java \ client/Client.java \ client/ClientListener.java \ client/DigestMD5ClientCallbackHandler.java |
Start the Server.
$ java -classpath server:mbeans:classpath Server & |
You will see confirmation of the creation of the MBean server, the initialization of the environment map and the launching of the JMXMP connector and its registration in the MBean server.
Start the Client.
$ java -classpath client:mbeans:classpath Client |
You will see confirmation of the creation of the JMXMP connector client, the initialization of the environment map, the connection to the MBean server and the performance of the various MBean operations followed by the closure of the connection.
In addition to the simple SASL security and the privacy-based security you can apply to JMXMP connectors, you can also define a custom SASL provider mechanism by defining your own SASL Provider.
The SASL mechanism used in this example is a straightforward customized mechanism called SAMPLE SASL. The example is found in the subdirectories of examplesDir/current/Security/jmxmp/sasl_provider. The SAMPLE SASL mechanism is defined in the SampleServer class, shown below.
Example 11-11 Custom SASL Server
import java.io.*; import javax.security.sasl.*; public class SampleServer implements SaslServer { private String username; private boolean completed = false; public String getMechanismName() { return "SAMPLE"; } public byte[] evaluateResponse(byte[] responseData) throws SaslException { if (completed) { throw new SaslException("Already completed"); } completed = true; username = new String(responseData); return null; } public String getAuthorizationID() { return username; } public boolean isComplete() { return completed; } public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException { throw new SaslException("No negotiated security layer"); } public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException { throw new SaslException("No negotiated security layer"); } public Object getNegotiatedProperty(String propName) { if (propName.equals(Sasl.QOP)) { return "auth"; } return null; } public void dispose() throws SaslException { } } |
The custom SASL SAMPLE mechanism defined by the SampleServer class, shown above, extends the SASL interface SaslServer. It simply calls the standard SaslServer methods one by one, to perform the following security operations:
A call to getMechanismName establishes that the SASL mechanism used must be SAMPLE.
Any response from the client end of the connection is evaluated by evaluateResponse, and an appropriate challenge to this response is generated.
The authorization ID for this connection is built from the client's user name.
Example 11-12 Custom SASL Server
public class SampleClient implements SaslClient { private byte[] username; private boolean completed = false; public SampleClient(String authorizationID) throws SaslException { if (authorizationID != null) { try { username = ((String)authorizationID).getBytes("UTF8"); } catch (UnsupportedEncodingException e) { throw new SaslException("Cannot convert " + authorizationID + " into UTF-8", e); } } else { username = new byte[0]; } } public String getMechanismName() { return "SAMPLE"; } public boolean hasInitialResponse() { return true; } public byte[] evaluateChallenge(byte[] challengeData) throws SaslException { if (completed) { throw new SaslException("Already completed"); } completed = true; return username; } public boolean isComplete() { return completed; } public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException { throw new SaslException("No negotiated security layer"); } public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException { throw new SaslException("No negotiated security layer"); } public Object getNegotiatedProperty(String propName) { if (propName.equals(Sasl.QOP)) { return "auth"; } return null; } public void dispose() throws SaslException { } } |
![]() ![]() |