2015-01-14 38 views
1

我想在我的Java應用程序中構建一個電話呼叫者。爲了這個便利,我使用了JAIN-SIP庫。在第一個INVITE之後,系統需要代理認證。第二個被邀請與conscructed「AuthenticationHelperImpl.class」的幫助:https://gitorious.org/0xdroid/external_nist-sip/source/1e0f37693341071f316852c8e05a08deef2b7fc4:java/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java#L311,包括代理認證頭和lloks,如:如何做SIP電話

INVITE sip:[email protected];maddr=fpbx.de SIP/2.0 
Call-ID: [email protected] 
CSeq: 2 INVITE 
From: "77735hk6iu" <sip:[email protected]> 
To: "+111111111111111" <sip:[email protected]> 
Via: SIP/2.0/UDP 192.168.17.107:34567;rport;branch=z9hG4bK-383337-5bc4fd6b7a616843fce9eaa243bcb10e 
Max-Forwards: 70 
Contact: <sip:[email protected]:5060> 
Content-Type: application/sdp 
Proxy-Authorization: Digest  username="77735hk6iu",realm="fpbx.de",nonce="VLaIxVS2h5muPS30F2zLdXHjup6ELyen",uri="sip:[email protected]:5060;maddr=fpbx.de",response="47ea578c6b01c99fd3ed2b41c60983df" 
Content-Length: 61 

v=0 
o=- 130565705777141827 1 IN IP4 192.168.17.107 
s=call 

我收到一開始碼100消息之後(「你的電話是非常重要的爲我們「)後跟408代碼消息(」請求超時「)。

我做了什麼imporve情況:

  1. 嘗試了不同的電話號碼格式:004930208488480, 04930208488480,049,0049,sdfhajfkhsk。對於所有這些數字我 成爲消息相同的組合。

  2. 試圖用端口在請求URI

  3. 試圖從請求URI除去MADDR。

  4. 試圖使用codek設置填充消息正文。

  5. 設置,並通過頭

從刪除RPORT如果現在我在做什麼錯了,請幫幫我。 預先感謝您。

+0

它看起來像一個NAT問題。監視雙方的流量以查看消息丟失的位置。你在任何地方廣告你的私人網絡地址192.168.17.107:34567。嘗試使用TCP而不是UDP進行驗證,在這種情況下應該更好地工作,這可能就足夠了。否則,請查看STUN並轉回或檢查您的遠程方是否可以配置爲以某種方式補償NAT。 –

回答

0

從請求URI和proxy-auth中刪除「maddr = fpbx.de」時問題部分解決。URI

FPR這是一個使用handleCahllenge方法與布爾參數:

inviteTid = authenticationHelper.handleChallenge(response, tid, sipProvider, 15, **true**); 

但我仍然不知道我可以一個acchieve sponaneous電話號碼。

2

我想,也許你的代理授權標題是錯誤的。也許你算錯了。我想分享我的決心。

authUser是您的phoneNumber。 (例如:77735hk6iu) authPass是您用戶的密碼。 味精是您的邀請請求(頭!)

AccountManagerImpl accountManagerImp = new AccountManagerImpl(authUser, AuthPass); 
     AuthenticationHelperImpl authenticationHelperImpl = new AuthenticationHelperImpl(accountManagerImp); 

     try { 
      this.authentication = authenticationHelperImpl.handleChallenge(msg, (SIPClientTransaction)trans); 

AuthenticationHelperImple.java類:

public AuthorizationHeader handleChallenge(Response challenge, ClientTransaction challengedTransaction) throws SipException { 


    SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest()); 

    ListIterator authHeaders = null; 

    if (challenge.getStatusCode() == Response.UNAUTHORIZED) { 
    authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME); 
    } 
    else { 
    if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) { 
     authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME); 
    } 
    else { 
     throw new IllegalArgumentException("Unexpected status code "); 
    } 
    } 

    if (authHeaders == null) { 
    throw new IllegalArgumentException("Could not find WWWAuthenticate or ProxyAuthenticate headers"); 
    } 

    WWWAuthenticateHeader authHeader = null; 
    while (authHeaders.hasNext()) { 
    authHeader = (WWWAuthenticateHeader) authHeaders.next(); 
    String realm = authHeader.getRealm(); 

    this.uri = challengedRequest.getRequestURI(); 

    this.requestMethod = challengedRequest.getMethod(); 
    this.requestBody = (challengedRequest.getContent() == null) ? "" : new String(challengedRequest.getRawContent()); 

    if (this.accountManager instanceof SecureAccountManager) { 
     UserCredentialHash credHash = ((SecureAccountManager) this.accountManager).getCredentialHash(challengedTransaction, 
                            realm); 
     if (credHash == null) { 
      logger.logDebug("Could not find creds"); 
      throw new SipException("Cannot find user creds for the given user name and realm"); 
     } 

     this.authorizationHeader = this.getAuthorization(requestMethod, uri.toString(), requestBody, authHeader, credHash); 
    } 
    else { 
     UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm); 
     if (userCreds == null) { 
      throw new SipException("Cannot find user creds for the given user name and realm"); 
     } 
     // sipDomain = userCreds.getSipDomain(); 
     // we haven't yet authenticated this realm since we were 
     // started. 

     this.authorizationHeader = this.getAuthorization(requestMethod, uri.toString(), requestBody, authHeader, userCreds); 
    } 
    } 

    return this.authorizationHeader; 

}

getAuthorization功能:

public AuthorizationHeader getAuthorization(String method, 
              String uri, 
              String requestBody, 
              WWWAuthenticateHeader authHeader, 
              UserCredentials userCredentials) throws SecurityException { 
    String response = null; 
    String qopList = authHeader.getQop(); 
    String qop = (qopList != null) ? "auth" : null; 
    String nc_value = "00000001"; 
    String cnonce = "xyz"; 

    try { 
    response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(), 
                 userCredentials.getUserName(), authHeader.getRealm(),userCredentials.getPassword(), authHeader.getNonce(), nc_value, // JvB added 
               cnonce, // JvB added 
               method, uri, requestBody, qop,logger); 
    } 
    catch (NullPointerException exc) { 
    throw new SecurityException("The received authenticate header was malformatted: " + exc.getMessage()); 
    } 

    AuthorizationHeader authorization = null; 
    try { 
     if (authHeader instanceof ProxyAuthenticateHeader) { 
     if (this.headerFactory != null) { 
      authorization = headerFactory.createProxyAuthorizationHeader(authHeader.getScheme()); 
     } 
     else { 
      authorization = new ProxyAuthorization(); 
      authorization.setScheme(authHeader.getScheme()); 
     } 
     } 
     else { 
     if (this.headerFactory != null) { 
      authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme()); 
     } 
     else { 
      authorization = new Authorization(); 
      authorization.setScheme(authHeader.getScheme()); 
     } 
     } 

     authorization.setUsername(userCredentials.getUserName()); 
     authorization.setRealm(authHeader.getRealm()); 
     authorization.setNonce(authHeader.getNonce()); 
     authorization.setParameter("uri", uri); 
     authorization.setResponse(response); 
     if (authHeader.getAlgorithm() != null) { 
      authorization.setAlgorithm(authHeader.getAlgorithm()); 
     } 

     if (authHeader.getOpaque() != null) { 
      authorization.setOpaque(authHeader.getOpaque()); 
     } 

     // jvb added 
     if (qop != null) { 
      authorization.setQop(qop); 
      authorization.setCNonce(cnonce); 
      authorization.setNonceCount(Integer.parseInt(nc_value)); 
     } 

     authorization.setResponse(response); 

    } catch (ParseException ex) { 
     throw new RuntimeException("Failed to create an authorization header!"); 
    } 

    return authorization; 

}

最後,您的this.authentication變量是ProxyAuthorizationHeader。您必須將此身份驗證放在您的INVITE消息中。而且,您會將SipMessage從事務或對話框發送到JAIN-SIP堆棧。

祝你好運!

+0

謝謝)在您回答之前,我也明白問題出在了代理服務器頭的這個「maddr」部分。但是你的代碼也很有幫助。 – user2957954

0

100消息是逐跳的,也就是說它只是意味着下一跳獲得了您的請求。其他消息通常是端到端的(所以,如果你有180個振鈴,那通常意味着被叫的終端發送180)。當其中一箇中繼段發送INVITE但從未得到響應時,408典型地顯示出來(當你的SIP棧在合理的時間內沒有得到臨時響應時,它可能會在內部產生 - 通常約32秒SIP定時器)。

我不知道您的網絡設置,但該消息中有多個私有IP(192.168.x.x種類)。如果我不得不猜測,你的第一跳就是將100發送回它從它接收到的IP /端口,但下一個響應在Via頭部之後(因爲它應該),並且在你不尊重該rport之後的跳躍參數,所以響應正在丟失。或者,您的NAT配置不良,並且正在關閉它爲INVITE創建的洞太快。

如果您的網絡邊緣有代理服務器發送此消息,則會在消息中添加錯誤的Via頭(可能使用內部IP而不是外部IP),或者它正在發送INVITE消息到了錯誤的地方(導致它從來沒有得到迴應),而408則來自它。