How to use the Java SASL API and CRAM-MD5
I'm currently playing with the Java SASL API and I wrote a little program to simulate a challenge response sequence using CRAM-MD5. However, I'm unsure about how to do this, as SaslClient and SaslServer only have methods evaluateChallenge(...) and evaluateResponse(...). I would expect SaslServer to have a method like issueChallenge(...) or something like that, but it has not. So what is the correct way to do this?
Below you find my (not working) code.
package mypackage;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
public class Main {
public static void main(String[] args) throws SaslException {
new Main().start();
}
private static class ClientHandler implements CallbackHandler {
@Override
public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackException {
for (Callback cb : cbs) {
if (cb instanceof NameCallback) {
System.out.println("Client - NameCallback");
NameCallback nc = (NameCallback)cb;
nc.setName("username");
} else if (cb instanceof PasswordCallback) {
System.out.println("Client - PasswordCallback");
PasswordCallback pc = (PasswordCallback)cb;
pc.setPassword("password".toCharArray());
}
}
}
}
private static class ServerHandler implements CallbackHandler {
@Override
public void handle(Callback[] cbs) throws IOException, UnsupportedCallbackExcept开发者_如何学JAVAion {
for (Callback cb : cbs) {
if (cb instanceof AuthorizeCallback) {
System.out.println("Server - AuthorizeCallback");
AuthorizeCallback ac = (AuthorizeCallback)cb;
ac.setAuthorized(true);
} else if (cb instanceof NameCallback) {
System.out.println("Server - NameCallback");
NameCallback nc = (NameCallback)cb;
nc.setName("username");
} else if (cb instanceof PasswordCallback) {
System.out.println("Server - PasswordCallback");
PasswordCallback pc = (PasswordCallback)cb;
pc.setPassword("password".toCharArray());
}
}
}
}
private void start() throws SaslException {
byte[] challenge;
byte[] response;
ClientHandler clientHandler = new ClientHandler();
ServerHandler serverHandler = new ServerHandler();
SaslClient sc = Sasl.createSaslClient(new String[] { "CRAM-MD5" }, null, "my_server", "FQHN", null, clientHandler);
SaslServer ss = Sasl.createSaslServer("CRAM-MD5", "my_server", "FQHN", null, serverHandler);
// Challenge response sequence (not working)
challenge = ss.evaluateResponse(null);
response = sc.evaluateChallenge(challenge);
ss.evaluateResponse(response);
if (ss.isComplete()) {
System.out.println("Authentication successful.");
}
}
}
Greetings, Fred
I was able to get the above code working by changing one line
from
challenge = ss.evaluateResponse(null);
to
challenge = ss.evaluateResponse(new byte[0]);
The javadoc for evaluateResponse() says
this method is called to prepare an appropriate next challenge to submit to the client
So I guess from the above, there is no need for a issueChallange()
method, evaluateResponse()
takes care of issuing the response.
精彩评论