如何使用Java SASL API和CRAM-MD5

时间:2010-01-16 15:11:57

标签: java authentication sasl challenge-response

我目前正在使用Java SASL API,我编写了一个小程序来使用CRAM-MD5模拟质询响应序列。但是,我不确定如何做到这一点,因为SaslClient和SaslServer只有方法evaluateChallenge(...)和evaluateResponse(...)。我希望SaslServer有一个像issueChallenge(...)这样的方法,但它没有。那么这样做的正确方法是什么?

在下面找到我的(不工作)代码。

    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, UnsupportedCallbackException {
   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.");
  }
 }
}

问候,弗雷德

1 个答案:

答案 0 :(得分:2)

我能够通过更改一行来获得上述代码

challenge = ss.evaluateResponse(null);

challenge = ss.evaluateResponse(new byte[0]);

evaluateResponse()的javadoc说

  

调用此方法以准备适当的下一个挑战以提交给客户

所以我从上面猜测,不需要issueChallange()方法,evaluateResponse()负责发布响应。