无法从 Asterisk 服务器获得 200 OK
Posted
技术标签:
【中文标题】无法从 Asterisk 服务器获得 200 OK【英文标题】:Unable to get 200 OK from Asterisk server 【发布时间】:2020-11-05 21:54:18 【问题描述】:我正在 Eclipse 中开发一个 SIP 客户端应用程序。我正在尝试注册到 Asterisk Server,但每次我得到 401 Unauthorized。在收到第一条 401 消息后,我还包含了 Authorization 标头。
REGISTER sip:xx.xx.xx.xx SIP/2.0
Call-ID: ef0ef86022c9a70909dfe9d7315c2929@192.168.0.6
CSeq: 1 REGISTER
From: <sip:Santanu@xx.xx.xx.xx>;tag=textclientv1.0
To: <sip:Santanu@xx.xx.xx.xx>
Via: SIP/2.0/UDP 192.168.0.6:5060
Max-Forwards: 70
Expires: 180
Content-Length: 0
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.0.6:5060;branch=z9hG4bK-363031-07183c4bdcc67d2a427747d132335a51;received=115.187.33.88;rport=5060
From: <sip:Santanu@xx.xx.xx.xx>;tag=textclientv1.0
To: <sip:Santanu@xx.xx.xx.xx>;tag=as7fe2c61e
Call-ID: ef0ef86022c9a70909dfe9d7315c2929@192.168.0.6
CSeq: 1 REGISTER
Server: Asterisk PBX 16.7.0
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH,MESSAGE
Supported: replaces,timer
WWW-Authenticate: Digest algorithm=MD5,realm="asterisk",nonce="75a0c702"
Content-Length: 0
REGISTER sip:xx.xx.xx.xx SIP/2.0
Call-ID: da592663fd88f0496380a3888844df95@192.168.0.6
CSeq: 1 REGISTER
From: <sip:Santanu@xx.xx.xx.xx>;tag=textclientv1.0
To: <sip:Santanu@xx.xx.xx.xx>
Via: SIP/2.0/UDP 192.168.0.6:5060
Max-Forwards: 70
Expires: 180
Authorization: Digest realm="asterisk",nonce="75a0c702",username="Santanu",uri="sip:xx.xx.xx.xx",algorithm=MD5,response="34c55995ca5bd9e5a1df9d21d1c8bd9e",cnonce="0a4f113b",nc=00000001,qop=auth
Content-Length: 0
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.0.6:5060;branch=z9hG4bK-363031-d081e9dc17d5bdaf73ecd2da30763b51;received=115.187.33.88;rport=5060
From: <sip:Santanu@xx.xx.xx.xx>;tag=textclientv1.0
To: <sip:Santanu@xx.xx.xx.xx>;tag=as2d43d078
Call-ID: da592663fd88f0496380a3888844df95@192.168.0.6
CSeq: 1 REGISTER
Server: Asterisk PBX 16.7.0
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH,MESSAGE
Supported: replaces,timer
WWW-Authenticate: Digest algorithm=MD5,realm="asterisk",nonce="788c190c"
Content-Length: 0
REGISTER sip:xx.xx.xx.xx SIP/2.0
Call-ID: 1e89a6010565507d291a10a7412fdf7d@192.168.0.6
CSeq: 1 REGISTER
From: <sip:Santanu@xx.xx.xx.xx>;tag=textclientv1.0
To: <sip:Santanu@xx.xx.xx.xx>
Via: SIP/2.0/UDP 192.168.0.6:5060
Max-Forwards: 70
Expires: 180
Authorization: Digest realm="asterisk",nonce="788c190c",username="Santanu",uri="sip:xx.xx.xx.xx",algorithm=MD5,response="6e1abc053061344d38dfb25211e4af49",cnonce="0a4f113b",nc=00000001,qop=auth
Content-Length: 0
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.0.6:5060;branch=z9hG4bK-363031-e1b94f1f52aa39e35c662fc3ae261d16;received=115.187.33.88;rport=5060
From: <sip:Santanu@xx.xx.xx.xx>;tag=textclientv1.0
To: <sip:Santanu@xx.xx.xx.xx>;tag=as58c8d6ed
Call-ID: 1e89a6010565507d291a10a7412fdf7d@192.168.0.6
CSeq: 1 REGISTER
Server: Asterisk PBX 16.7.0
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH,MESSAGE
Supported: replaces,timer
WWW-Authenticate: Digest algorithm=MD5,realm="asterisk",nonce="33185dc4"
Content-Length: 0
我的代码如下:
public class SipInit implements SipListener
private String ip;
private SipFactory sipFactory;
private Properties properties;
private SipStack sipStack;
@SuppressWarnings("unused")
private MessageFactory messageFactory;
private HeaderFactory headerFactory;
private AddressFactory addressFactory;
private ListeningPoint listeningPoint;
private int port;
private String protocol;
private SipProvider sipProvider;
private String username1;
private String username2;
private Address contactAddress;
@SuppressWarnings("unused")
private ContactHeader contactHeader;
private String server;
private char[] tag;
private Request request;
private String password;
private ClientTransaction inviteTid;
private Dialog dialog;
private Response resp;
int cseq = 0;
public void init() throws ParseException
try
// Get the local IP address.
this.ip = "192.168.0.6";//InetAddress.getLocalHost().getHostAddress();
//this.tag=" ".toCharArray();
// Create the SIP factory and set the path name.
this.sipFactory = SipFactory.getInstance();
this.port=5060;
this.protocol="udp";
this.server="178.63.254.99";
this.username1="Santanu";
this.username2="Arijit";
this.password="voip123";
this.sipFactory.setPathName("gov.nist");
// Create and set the SIP stack properties.
this.properties = new Properties();
this.properties.setProperty("javax.sip.STACK_NAME", "stack");
this.properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");
this.properties.setProperty(
"gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
this.properties.setProperty("gov.nist.javax.sip.DEBUG_LOG",
"mss-jsip-debuglog.txt");
this.properties.setProperty("gov.nist.javax.sip.SERVER_LOG",
"mss-jsip-messages.xml");
// Create the SIP stack.
this.sipStack = this.sipFactory.createSipStack(this.properties);
// Create the SIP message factory.
this.messageFactory = this.sipFactory.createMessageFactory();
// Create the SIP header factory.
this.headerFactory = this.sipFactory.createHeaderFactory();
// Create the SIP address factory.
this.addressFactory = this.sipFactory.createAddressFactory();
// Create the SIP listening point and bind it to the local IP
// address, port and protocol.
this.listeningPoint = this.sipStack.createListeningPoint(this.ip,
this.port, this.protocol);
// Create the SIP provider.
this.sipProvider = this.sipStack
.createSipProvider(this.listeningPoint);
// Add our application as a SIP listener.
this.sipProvider.addSipListener(this);
// Create the contact address used for all SIP messages.
this.contactAddress = this.addressFactory.createAddress("sip:" + this.username1 + "@"
+ this.ip + ";transport=udp");
// Create the contact header used for all SIP messages.
this.contactHeader = this.headerFactory
.createContactHeader(contactAddress);
// Display the local IP address and port in the text area.
catch (Exception e)
e.printStackTrace();
// If an error occurs, display an error message box and exit.
System.exit(-1);
//r.setStatusCode(200);
register();
public void register() throws NullPointerException
Object logger;
try
cseq++;
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
ViaHeader viaHeader = this.headerFactory.createViaHeader(this.ip,
this.port, "udp", "abcd");
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.
@SuppressWarnings("deprecation")
CSeqHeader cSeqHeader = this.headerFactory.createCSeqHeader(cseq,
"REGISTER");
Address fromAddress = addressFactory.createAddress("sip:"
+ username1 + '@' + server);
FromHeader fromHeader = this.headerFactory.createFromHeader(
fromAddress, "textclientv1.0");//String.valueOf(this.tag)//Integer.toString(hashCode())
// 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(viaHeader);
request.addHeader(maxForwardsHeader);
request.addHeader(fromHeader);
request.addHeader(toHeader);
request.addHeader(callIdHeader);
request.addHeader(cSeqHeader);
request.addHeader(contactHeader);
/*URI requestURI = addressFactory.createURI("sip:" + server);
Request request = messageFactory.createRequest(requestURI,
Request.REGISTER, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwardsHeader);
request.addHeader(contactHeader);*/
/*Request request = messageFactory.createRequest(requestURI,
Request.REGISTER, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwardsHeader);*/
//Response response=this.messageFactory.createResponse(200, request);
HeaderFactory header=this.sipFactory.createHeaderFactory();
ExpiresHeader eh = header.createExpiresHeader(3060);
request.addHeader(eh);
if (resp != null)
boolean retry = true;
AuthorizationHeader authHeader = makeAuthHeader(headerFactory, resp,
request, username1, password);
request.addHeader(authHeader);
System.out.println(""+ request);
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.
//debug("Request sent:\n" + request.toString() + "\n\n");
catch (Exception e)
// If an error occurred, display the error.
e.printStackTrace();
//debug("Request sent failed: " + e.getMessage() + "\n");
@Override
public void processDialogTerminated(DialogTerminatedEvent arg0)
// TODO Auto-generated method stub
@Override
public void processIOException(IOExceptionEvent arg0)
// TODO Auto-generated method stub
@Override
public void processRequest(RequestEvent arg0)
// TODO Auto-generated method stub
@Override
public void processResponse(ResponseEvent arg0)
// TODO Auto-generated method stub
resp=arg0.getResponse();
//CSeqHeader cseq = (CSeqHeader) resp.getHeader(CSeqHeader.NAME);
try
Thread.sleep(1000);
catch (InterruptedException e)
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(resp);
//if(cseq<=2)
register();
@Override
public void processTimeout(TimeoutEvent arg0)
// TODO Auto-generated method stub
@Override
public void processTransactionTerminated(TransactionTerminatedEvent arg0)
// TODO Auto-generated method stub
private AuthorizationHeader makeAuthHeader(HeaderFactory headerFactory2, Response response, Request request, String username2,
String password2) throws ParseException
// TODO Auto-generated method stub
// Authenticate header with challenge we need to reply to
WWWAuthenticateHeader ah_c = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
// Authorization header we will build with response to challenge
AuthorizationHeader ah_r = headerFactory.createAuthorizationHeader(ah_c.getScheme());
// assemble data we need to create response string
URI request_uri = request.getRequestURI();
String request_method = request.getMethod();
String nonce = ah_c.getNonce();
String algrm = ah_c.getAlgorithm();
String realm = ah_c.getRealm();
MessageDigest mdigest;
try
mdigest = MessageDigest.getInstance(algrm);
// A1
String A1 = username2 + ":" + realm + ":" + password2;
String HA1 = toHexString(mdigest.digest(A1.getBytes()));
// A2
String A2 = request_method.toUpperCase() + ":" + request_uri ;
String HA2 = toHexString(mdigest.digest(A2.getBytes()));
// KD
String KD = HA1 + ":" + nonce + ":" + HA2;
String responsenew = toHexString(mdigest.digest(KD.getBytes()));
ah_r.setUsername(username2);
ah_r.setRealm(realm);
ah_r.setNonce(nonce);
ah_r.setURI(request_uri);
ah_r.setAlgorithm(algrm);
ah_r.setResponse(responsenew);
catch (NoSuchAlgorithmException e)
// TODO Auto-generated catch block
e.printStackTrace();
return ah_r;
private static final char[] toHex = '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' ;
static String toHexString(byte b[])
int pos = 0;
char[] c = new char[b.length * 2];
for (int i = 0; i < b.length; i++)
c[pos++] = toHex[(b[i] >> 4) & 0x0F];
c[pos++] = toHex[b[i] & 0x0f];
return new String(c);
请指教。
【问题讨论】:
【参考方案1】:你好
第一个 401 在“WWW-Authenticate:”中用“nonce”回答,客户端必须在下一次 REGISTER 时用“Authorization:”中的正确“response”回答
找出服务器不接受“响应”的原因。 ( 密码错误? ) 具有有效“响应”的第二个 REGISTER 看起来像...
[Jul 16 14:54:48] REGISTER sip:osmc SIP/2.0
[Jul 16 14:54:48] Via: SIP/2.0/UDP 192.168.178.1:5060;rport;branch=z9hG4bK0F70B6BAE0059522
[Jul 16 14:54:48] Route: <sip:192.168.178.22:5070;lr>
[Jul 16 14:54:48] From: <sip:1001@osmc>;tag=2183661807
[Jul 16 14:54:48] To: <sip:1001@osmc>
[Jul 16 14:54:48] Call-ID: C001CA03F6BF2794@192.168.178.1
[Jul 16 14:54:48] CSeq: 1704 REGISTER
[Jul 16 14:54:48] Contact: <sip:1001@192.168.178.1;uniq=0FA6428E93F9F1194B723E54CA22B>
[Jul 16 14:54:48] Authorization: Digest username="1001", realm="asterisk", nonce="4b2486f6", uri="sip:osmc", response="00c53b8da7d68da98a56bcd00f153f33", algorithm=MD5
[Jul 16 14:54:48] Max-Forwards: 70
[Jul 16 14:54:48] Expires: 1800
[Jul 16 14:54:48] User-Agent: AVM FRITZ!Box 7560 149.07.12 (Jul 3 2019)
[Jul 16 14:54:48] Supported: 100rel,replaces
[Jul 16 14:54:48] Allow-Events: telephone-event,refer,reg
[Jul 16 14:54:48] Allow: INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH
[Jul 16 14:54:48] Accept: application/sdp, multipart/mixed
[Jul 16 14:54:48] Accept-Encoding: identity
[Jul 16 14:54:48] Content-Length: 0
[Jul 16 14:54:48]
[Jul 16 14:54:48] <------------->
[Jul 16 14:54:48] --- (18 headers 0 lines) ---
[Jul 16 14:54:48] Sending to 192.168.178.1:5060 (no NAT)
[Jul 16 14:54:48]
[Jul 16 14:54:48] <--- Transmitting (no NAT) to 192.168.178.1:5060 --->
[Jul 16 14:54:48] SIP/2.0 200 OK
[Jul 16 14:54:48] Via: SIP/2.0/UDP 192.168.178.1:5060;branch=z9hG4bK0F70B6BAE0059522;received=192.168.178.1;rport=5060
[Jul 16 14:54:48] From: <sip:1001@osmc>;tag=2183661807
[Jul 16 14:54:48] To: <sip:1001@osmc>;tag=as793919e9
[Jul 16 14:54:48] Call-ID: C001CA03F6BF2794@192.168.178.1
[Jul 16 14:54:48] CSeq: 1704 REGISTER
[Jul 16 14:54:48] Server: PiBX
[Jul 16 14:54:48] Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
[Jul 16 14:54:48] Supported: replaces, timer
[Jul 16 14:54:48] Expires: 1800
[Jul 16 14:54:48] Contact: <sip:1001@192.168.178.1;uniq=0FA6428E93F9F1194B723E54CA22B>;expires=1800
[Jul 16 14:54:48] Date: Thu, 16 Jul 2020 12:54:48 GMT
[Jul 16 14:54:48] Content-Length: 0
编辑-我认为您忘记了联系人: * 完全接受并使用
;expires=1800
扩展它,例如客户必须遵循。不管客户要求什么。服务器有关于到期的最后一句话。不规则:来自客户端的Expires: 0
表示:取消注册我
【讨论】:
以上是关于无法从 Asterisk 服务器获得 200 OK的主要内容,如果未能解决你的问题,请参考以下文章
具有标题和数据的POST请求导致200 ok响应但未添加用户
状态 200 OK(),角度承诺抛出错误——没有“访问控制允许来源”
PhoneRTC Signal and Turn 服务器与 Asterisk 服务器