8

我正在使用 Jain Sip 库,尝试创建与星号服务器的连接。我一直在使用此页面中的 textclient 示例应用程序: http ://www.oracle.com/technetwork/articles/entarch/introduction-jain-sip-090386.html

但这实际上并没有通过服务器进行身份验证。我可以向服务器上的用户发送消息,但我通常需要在服务器上进行用户/密码身份验证。

据我所知,我必须使用“javax.sip.OUTBOUND_PROXY”属性,但我找不到任何关于如何设置用户名或密码的文档。有没有其他人在这方面取得过任何成功?

4

3 回答 3

9

我在注册中找到的最佳示例在这里。如果万一有一天链接干涸,以下是要点:

REGISTER 请求用于更新用户在 REGISTRAR 服务器上的当前位置。应用程序发送 REGISTER 消息通知服务器其当前位置,该位置又存储在位置服务器中。当呼叫者呼叫用户时,代理服务器使用此信息来查找被呼叫者的位置。

注册请求应由客户端定期发送。REGISTER 请求的有效性由 Expires 标头确定。

流动

图片

样品请求

REGISTER sip:sip.linphone.org SIP/2.0
Call-ID: 0a0f14355fa76ae6435b98bfe085baf9@223.1.1.128
CSeq: 1 REGISTER
From: <sip:vkslabs@sip.linphone.org>;tag=-1427592833
To: <sip:vkslabs@sip.linphone.org>
Max-Forwards: 70
Via: SIP/2.0/TCP 223.1.1.128:5060;branch=z9hG4bK-323532-2a454f4ec2a4213f6d6928eba479521d
Contact: <sip:vkslabs@223.1.1.128;transport=tcp>
Content-Length: 0

现在让我们看看如何使用 NIST SIP 堆栈构建上述请求。

第一步是创建一个实现 SIPListener 的类。确保您的 SIP 堆栈正在初始化 NIST JAIN SIP 堆栈。

  1. 创建 Call-ID 标头

    CallIdHeader callIdHeader = this.sipProvider.getNewCallId();

  2. 创建 Cseq 标头

    CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(cseq, "REGISTER");

  3. 创建自标头

    地址 fromAddress = addressFactory.createAddress("sip:" + username + '@' + server); FromHeader fromHeader = this.headerFactory.createFromHeader(fromAddress, String.valueOf(this.tag));

  4. 创建到标题

    ToHeader toHeader = this.headerFactory.createToHeader(fromAddress, null);

  5. 创建 Max-Forwards 标头

    MaxForwardsHeader maxForwardsHeader = this.headerFactory.createMaxForwardsHeader(70);

  6. 创建 Via 标头

    ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip, this.port, "tcp", null); viaHeaders.add(viaHeader);

  7. 创建联系人标题

    this.contactAddress = this.addressFactory.createAddress("sip:" + this.username + '@' + this.ip + "transport=tcp");

    // 创建用于所有 SIP 消息的联系人标头。this.contactHeader = this.headerFactory.createContactHeader(contactAddress);

一旦创建了所有标头,就该创建请求本身了。

request = this.messageFactory.createRequest("REGISTER sip:" + server + "SIP/2.0\r\n\r\n"); 
request.addHeader(callIdHeader);
request.addHeader(cSeqHeader); 
request.addHeader(fromHeader);
request.addHeader(toHeader); 
request.addHeader(maxForwardsHeader);
request.addHeader(viaHeader); 
request.addHeader(contactHeader);

现在请求对象已经创建了所有必要的标头,是时候发送请求了。

inviteTid = sipProvider.getNewClientTransaction(request); // send the request out. 
inviteTid.sendRequest();

成功发送请求后,将使用 SIPListener 中的 processResponse 回调将响应传递给应用程序。

public void processResponse(ResponseEvent responseEvent) { 
  int statusCode = responseEvent.getResponse().getStatusCode(); 
}

代码

public void register(Response response) {
  try {
  cseq++;
  ArrayList viaHeaders = new ArrayList();
  ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,
  this.port, "tcp", null);
  viaHeaders.add(viaHeader);
  // The "Max-Forwards" header.
  MaxForwardsHeader maxForwardsHeader = this.headerFactory
  .createMaxForwardsHeader(70);
  // The "Call-Id" header.
  CallIdHeader callIdHeader = this.sipProvider.getNewCallId();
  // The "CSeq" header.
  CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(cseq,
  "REGISTER");

  Address fromAddress = addressFactory.createAddress("sip:"
  + username + '@' + server);

  FromHeader fromHeader = this.headerFactory.createFromHeader(
  fromAddress, String.valueOf(this.tag));
  // The "To" header.
  ToHeader toHeader = this.headerFactory.createToHeader(fromAddress,
  null);

  // this.contactHeader = this.headerFactory
  // .createContactHeader(contactAddress);

  request = this.messageFactory.createRequest("REGISTER sip:"
  + server + " SIP/2.0\r\n\r\n");
  request.addHeader(callIdHeader);
  request.addHeader(cSeqHeader);
  request.addHeader(fromHeader);
  request.addHeader(toHeader);
  request.addHeader(maxForwardsHeader);
  request.addHeader(viaHeader);
  request.addHeader(contactHeader);
  if (response != null) {
  retry = true;
  AuthorizationHeader authHeader = Utils.makeAuthHeader(headerFactory, response,
  request, username, password);
  request.addHeader(authHeader);
  }
  inviteTid = sipProvider.getNewClientTransaction(request);
  // send the request out.
  inviteTid.sendRequest();
  this.dialog = inviteTid.getDialog();
  // Send the request statelessly through the SIP provider.
  //            this.sipProvider.sendRequest(request);

  // Display the message in the text area.
  logger.debug("Request sent:\n" + request.toString() + "\n\n");
  } catch (Exception e) {
  // If an error occurred, display the error.
  e.printStackTrace();
  logger.debug("Request sent failed: " + e.getMessage() + "\n");
  }
}

您还可以在此处查看有关身份验证的参考帖子。如果万一有一天链接干涸,以下是要点:

在 SIP 请求期间,如果服务器以 401 Proxy Authentication Required 或 401 Unauthorized 响应,则意味着客户端必须使用 MD5 质询再次重放相同的请求。

客户端应该使用来自响应头 WWW-Authenticate 的 nonce 值。

WWW-Authenticate: Digest realm="sip.linphone.org", nonce="JbAO1QAAAAA3aDI0AADMobiT7toAAAAA", opaque="+GNywA==", algorithm=MD5, qop="auth"

客户端应使用 nonce 生成 MD5 质询,并使用 Authorization 标头再次发出原始请求。

创建 MD5 挑战的步骤

  1. 使用用户名 + “:” + 领域 + “:” + 密码创建第一个 MD5 哈希

    字符串 a1 = 用户名 + ":" + 领域 + ":" + 密码;字符串 ha1 = toHexString(mdigest.digest(a1.getBytes()));

  2. 使用 request_method + “:” + request_uri 创建第二个 MD5 哈希

    字符串 a2 = request_method.toUpperCase() + ":" + request_uri; 字符串 ha2 = toHexString(mdigest.digest(a2.getBytes()));

  3. 如果响应标头中的 qop 是“auth”,则使用步骤 3a 计算最终的 MD5 哈希,否则如果它未定义或为空,请参阅步骤 3b。

3a。使用 ha1 + “:” + nonce + “:” + nonceCount + “:” + cNonce + “:” + qop + “:” + ha2 创建最终的 MD5 字符串

String finalStr = ha1 + ":" + nonce + ":" + nonceCount + ":" + cNonce + ":" + qop + ":" + ha2; 
String response = toHexString(mdigest.digest(finalStr.getBytes()));

3b。使用 ha1 + “:” + nonce + “:” + ha2 创建最终的 MD5 字符串

String finalStr = ha1 + ":" + nonce + ":" + ha2; 
String response = toHexString(mdigest.digest(finalStr.getBytes()));
于 2013-09-17T21:52:41.743 回答
4

从这里查看示例http://code.google.com/p/jain-sip/source/browse/#git%2Fsrc%2Fexamples%2Fauthorization

为什么你需要去这个低级别,你可能最好使用 SIP Servlets 容器,比如 Mobicents http://code.google.com/p/sipservlets/

于 2012-10-23T20:34:57.387 回答
2

您可能还想查看封装了上述步骤的 ClientAuthenticationHelper 类:请参阅包 gov.nist.javax.sip.clientauthutils

我相信代码库中有一个使用示例。

于 2014-04-11T16:28:11.837 回答