Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

Описание

Допустим, возникла задача ограничить доступ пользователей к серверу, основываясь на домене, например, разрешить просмотр видео только с определенного домена. Эта задача может быть решена при помощи REST hooks.

WCS передает в REST-запросе типа 1 "connect" к бэкенд-серверу поле "origin", содержащее доменное имя WCS-сервера, по которому к нему обратился пользователь, например

{
  "nodeId" : "5tWOFn5ZoMQs22KrEls2Ulhee57hQO9D",
  "appKey" : "defaultApp",
  "sessionId" : "/5.44.168.45:53438/abcdef0123456789",
  "useWsTunnel" : false,
  "useWsTunnelPacketization2" : false,
  "useBase64BinaryEncoding" : false,
  "mediaProviders" : [ "WebRTC", "MSE", "WSPlayer" ],
  "clientVersion" : "0.5.28",
  "clientOSVersion" : "5.0 (Windows)",
  "clientBrowserVersion" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0",
  "keepAlive" : false,
  "origin" : "https://test2.flashphoner.com:8888"
}

Таким образом, для авторизации пользователя по домену необходимо реализовать REST hook типа 1 "connect".

Пример реализации REST hook типа 1 для авторизации по домену

Требования к реализации

1. REST hook типа 1 должен быть доступен на веб-сервере как

http://yourhost/rest-hooks/connect

2. REST hook должен обрабатывать POST application/json HTTP запросы.
3. REST hook должен возвращать в теле ответа в точности то же, что он получил в запросе, за исключением настройки restClientConfig.
4. WCS сервер должен быть настроен на работу с REST hook следующим образом:

ssh -p 2001 admin@localhost
>update app defaultApp -l http://yourhost/rest-hooks

Обращения к REST методу можно отслеживать в логе сервера

tail -f /usr/local/FlashphonerWebCallServer/logs/server_logs/flashphoner.log

Код примера и его разбор

В первых строках скрипта определяется метод и декодируется тело запроса. Здесь же задаем домен для авторизации:

<?php

$api_method = array_pop(explode("/", $_SERVER['REQUEST_URI']));
$incoming_data = json_decode(file_get_contents('php://input'), true);
$domain = "yourdomain.com";

Начинается обработка метода "connect". Здесь определяется переданное в запросе поле "origin" и заполняется поле "restClientConfig" для ответа:

switch($api_method) {
    case"connect":	
	
	$origin = $incoming_data['origin'];	
	
	//logs
	error_log("sessionId: " . $incoming_data['sessionId']);
	error_log("origin: " . $origin);	
	
	
	$rest_client_config = json_decode(file_get_contents('rest_client_config.json'), true);	
	$incoming_data['restClientConfig'] = $rest_client_config;

Проверка домена. Если домен не найден, вызывается функция ubnormalResponse для формирования отрицательного ответа

	$found = strpos($origin, $domain);


	if ($found !== false){
	    error_log("User authorized by domain " . $domain);
	}else{
	    error_log("User not authorized by domain: " . $domain . " Connection failed with 403 status.");
	    ubnormalResponse(403);
	}
	break;
}

Вывод ответа на запрос

header('Content-Type: application/json');
echo json_encode($incoming_data);

Функция ubnormalResponse завершает скрипт:

function ubnormalResponse($code) {
    if ($code == 403) {
	header('HTTP/1.1 403 Forbidden', true, $code);
    } else {
	header(':', true, $code);
    }
    die();
}
?>
Пример скрипта целиком
<?php

$api_method = array_pop(explode("/", $_SERVER['REQUEST_URI']));
$incoming_data = json_decode(file_get_contents('php://input'), true);
$domain = "yourdomain.com";

switch($api_method) {
    case"connect":	
	
	$origin = $incoming_data['origin'];	
	
	//logs
	error_log("sessionId: " . $incoming_data['sessionId']);
	error_log("origin: " . $origin);	
	
	
	$rest_client_config = json_decode(file_get_contents('rest_client_config.json'), true);	
	$incoming_data['restClientConfig'] = $rest_client_config;


	$found = strpos($origin, $domain);

	if ($found !== false){
	    error_log("User authorized by domain " . $domain);
	}else{
	    error_log("User not authorized by domain: " . $domain . " Connection failed with 403 status.");
	    ubnormalResponse(403);
	}
	break;
}
header('Content-Type: application/json');
echo json_encode($incoming_data);


function ubnormalResponse($code) {
    if ($code == 403) {
	header('HTTP/1.1 403 Forbidden', true, $code);
    } else {
	header(':', true, $code);
    }
    die();
}
?>
Файл настройки restClientConfig для ответа на запрос rest_client_config.json
{
  "ConnectionStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "RegistrationStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "sendXcapRequest" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "XcapStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "sendDtmf" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "call" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "OnCallEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "answer" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "hangup" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "hold" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "unhold" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "transfer" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "OnTransferEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "FAIL",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "TransferStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "CallStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "sendMessage" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "FAIL",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "OnMessageEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "MessageStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "publishStream" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "unPublishStream" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "playStream" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "stopStream" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "StreamStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "subscribe" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "SubscriptionStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "OnDataEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "DataStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "submitBugReport" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "BugReportStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "pushLogs" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "RecordingStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "ErrorStatusEvent" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  },
  "disconnect" : {
    "clientExclude" : "",
    "restExclude" : "",
    "restOnError" : "LOG",
    "restPolicy" : "NOTIFY",
    "restOverwrite" : ""
  }
}




  • No labels