激活服务器(GB28181学习笔记3)

一、注册过程说明这里使用一台海康的摄像头做实际测试。GB28281注册过程有鉴权、不鉴权两种,本文实现的带鉴权的方式,基于GB281812016版。本文原本想用C++库实现,但我这只有QT,配置基于第三方sip包的环境太不熟练,花很长时间没搞好,为节省时间暂且用nodejs先代用。不带鉴权:带鉴权:1. 设备设置2. 注册过程1. 设备发送register注册消息2. 服务器返回401 未登陆3. 设备发送登陆认证主要是要计算当中的response值,认证计算过程:下面使用kd函数,表示对字符串使用 冒号 拼接后,计算md5,即:如: kd(a,b)=md5(a+":"+b)kd(a,b) = md5(a + ":" + b)kd(a,b)=md5(a+":"+b)HA1=kd(username,realm,passwd)HA2=kd(Method,Uri)HA1=kd(username,realm,passwd)HA2=kd(Method,Uri)HA1=kd(username,realm,passwd)HA2=kd(Method,Uri)response有两种情况,一种带nonce,一种不带。不带nonce:response=kd(ha1,nonce,ha2)response = kd(ha1,nonce,ha2)response=kd(ha1,nonce,ha2)带nonceresponse=kd(ha1,nonce,nc,cnonce,qop,ha2)response = kd(ha1,nonce,nc,cnonce,qop,ha2)response=kd(ha1,nonce,nc,cnonce,qop,ha2)4. 服务端校验正确,返回200ok接下来服务端可以请求设备目录。本文主要实现REGISTER的部分。3. 签名校验二、实现过程依赖:https://github.com/kirm/sip.js1. 启动 sipsip.start({
logger: {
send: function(message, address) {
// logger.info("==send==:" , message,address);
},
recv: function(message, address) {
// logger.info("==recv==:" , message,address);
}
}
},function(rq) {
});
1234567891011返回值解析:if(rq.method ==='REGISTER') {
logger.info('call register');

var username = sip.parseUri(rq.headers.to.uri).user;

logger.info('register username',username);
var userinfo = registry[username];
//logger.info('userinfo', userinfo);

if(!userinfo) {
// 没有登记的用户,这里直接禁止授权
logger.error('没有登记的用户,这里直接禁止授权:' , username);
var session = {realm: realm};
sip.send(digest.challenge(session, sip.makeResponse(rq, 401, 'Unauthorized')));
return;
}
else {
userinfo.session = userinfo.session || {realm: realm};
if(!digest.authenticateRequest(userinfo.session, rq, {user: username, password: userinfo.password})) {
sip.send(digest.challenge(userinfo.session, sip.makeResponse(rq, 401, 'Unauthorized')));
}
else {
// 完成授权
userinfo.contact = rq.headers.contact;
var rs = sip.makeResponse(rq, 200, 'Ok');
rs.headers.contact = rq.headers.contact;
sip.send(rs);
}
}
}
123456789101112131415161718192021222324252627282930三、完整代码
var log4js = require('log4js');

log4js.configure({
appenders: {
out: { type: 'stdout' },
app: { type: 'file', filename: 'application.log' }
},
categories: {
// getLogger 参数为空时,默认使用该分类
default: { appenders: [ 'out', 'app' ], level: 'debug' }
}
});

var logger = log4js.getLogger();
const log4js_extend = require("log4js-extend");
log4js_extend(log4js, {
path: __dirname + "/a.log",
format: "at @name (@file:@line:@column)"
});

var parseString = require('xml2js').parseString;
var sip = require('sip');
var digest = require('sip/digest');
var os = require('os');

var server_account = '34020000002000000001';

var registry = {
'34020000001110000001': {password: '你的设备密码'}
};

debugger;
var realm ='3402000000';

logger.info('localhost name='+realm);
sip.start({
logger: {
send: function(message, address) {
// logger.info("==send==:" , message,address);
},
recv: function(message, address) {
// logger.info("==recv==:" , message,address);
}
}
},
function(rq) {
try {
logger.info('———————-',rq);
if(rq.method ==='REGISTER') {
logger.info('call register');

var username = sip.parseUri(rq.headers.to.uri).user;

logger.info('register username',username);
var userinfo = registry[username];
//logger.info('userinfo', userinfo);

if(!userinfo) {
// 没有登记的用户,这里直接禁止授权
logger.error('没有登记的用户,这里直接禁止授权:' , username);
var session = {realm: realm};
sip.send(digest.challenge(session, sip.makeResponse(rq, 401, 'Unauthorized')));
return;
}
else {
// 这里应该对server_account再校验一下。但有的网上测试IPC程序server_account没用到uri里。这里先简单实现下原理。
userinfo.session = userinfo.session || {realm: realm};
if(!digest.authenticateRequest(userinfo.session, rq, {user: username, password: userinfo.password})) {
sip.send(digest.challenge(userinfo.session, sip.makeResponse(rq, 401, 'Unauthorized')));
}
else {
// 完成授权
userinfo.contact = rq.headers.contact;
var rs = sip.makeResponse(rq, 200, 'Ok');
rs.headers.contact = rq.headers.contact;
sip.send(rs);
}
}
}

} catch(e) {
logger.error(e);
sip.send(sip.makeResponse(rq, 500, "Server Internal Error"));
}
});

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889正常运行后,可以看到海康摄像头处于在线状态。


本文出自快速备案,转载时请注明出处及相应链接。

本文永久链接: https://www.xiaosb.com/beian/37052/