API e exemplo de código para servidor de portal externo (Omada Controller 2.6.0 a 3.2.17)
Adequado para Omada Controller 2.6.0 até 3.2.17.
Para Omada Controller 2.5.4 ou inferior, consulte FAQ928
Para Omada Controller 4.1.5 até 4.4.6, consulte FAQ2907
Para Omada Controller 5.0.15 ou superior, consulte FAQ3231
Este documento descreve os requisitos ao estabelecer um servidor de portal externo. Para saber como configurar o External Portal Server, consulte FAQ-896 (etapa 2 da seção 5).
A imagem abaixo mostra o fluxo de dados entre o cliente sem fio, o dispositivo EAP, o Omada Controller, o servidor de portal e o servidor de autenticação, o que pode ajudar você a entender melhor os requisitos para a criação de um servidor de portal externo.

1. O cliente sem fio se conecta ao SSID no qual a autenticação por portal está habilitada e tenta acessar a Internet. O dispositivo EAP intercepta a requisição HTTP do cliente e a redireciona para o Omada Controller. Em seguida, o cliente enviará uma requisição GET ao Omada Controller com a string de consulta “cid=client_mac&ap=ap_mac&ssid=ssid_name&t=time_since_epoch&rid=Radio_id” na URL, de acordo com a resposta HTTP recebida do EAP. (Etapa 1 e Etapa 2)
2. O Omada Controller então redireciona o cliente para o servidor de portal externo respondendo com uma resposta HTTP com código de status 302 Found ao cliente. A resposta HTTP com esse código também fornecerá a URL do servidor de portal externo no campo location. A URL também contém a string de consulta. Para Omada Controller 2.6.0 ou superior, a URL é http://portal_server_ip?cid=client_mac&ap=ap_mac&ssid=ssid_name&t=time_since_epoch&rid=Radio_id&site=site_name. (Etapa 3 e Etapa 4)
O significado dos parâmetros está listado na Tabela 1 – Explicação dos parâmetros.

3. O cliente enviará uma requisição GET ao servidor de portal externo utilizando a URL mencionada acima. (Etapa 5)
4. O servidor de portal externo deve ser capaz de interceptar e registrar os parâmetros presentes na string de consulta da requisição GET e retornar uma página web com formulário de autenticação ao cliente sem fio. (Etapa 6)
5. As informações de autenticação do cliente sem fio serão enviadas ao servidor de portal, e o servidor de portal encaminhará essas informações ao servidor de autenticação (Etapa 7 e Etapa 8). Entretanto, a forma como o servidor de portal obtém as informações de autenticação do cliente e como ele se comunica com o servidor de autenticação dependem da sua própria implementação, o que está fora do escopo deste artigo.
6. O servidor de autenticação verifica as informações de autenticação e retorna o resultado ao servidor de portal. (Etapa 9)
NOTA: Neste exemplo, o servidor de portal e o servidor de autenticação estão separados. Porém, eles podem ser instalados no mesmo servidor, se desejado. O método de autenticação também fica a seu critério. Apenas certifique-se de que o servidor de portal saiba quando a autenticação for bem-sucedida.
7. Se a autenticação for bem-sucedida, o servidor de portal deverá enviar as informações do cliente ao Omada Controller chamando a API do Omada Controller. Primeiro, é necessário fazer o login no Omada Controller enviando uma requisição POST. A URL da requisição será https://controller_server_ip:https_port/login e ela deverá conter os dados “name=the_username_of_controller&password=the_password_of_controller” em formato JSON no corpo da mensagem HTTP.
Por exemplo,
private static function login()
{
$ch = curl_init();
// post
curl_setopt($ch, CURLOPT_POST, TRUE);
// Definir retorno como valor, não retornar para a página
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Configurar cookies
curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE_FILE_PATH);
curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE_FILE_PATH);
// Permitir certificados autoassinados
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// Chamada da API
curl_setopt($ch, CURLOPT_URL, CONTROLLER_SERVER . "/login");
curl_setopt($ch, CURLOPT_POSTFIELDS, "name=" . CONTROLLER_USER ."&password=" . CONTROLLER_PASSWORD);
$res = curl_exec($ch);
$resObj = json_decode($res);
// Prevenir CSRF
if($resObj->success == true){
self::setCSRFToken($resObj->value);
}
curl_close($ch);
}
private static function setCSRFToken($token){
$myfile = fopen(TOKEN_FILE_PATH, "w") or die("Não foi possível abrir o arquivo!");
fwrite($myfile, $token);
fclose($myfile);
return $token;
}
(Etapa 10)
8. Se o servidor de portal tiver efetuado login no controller com sucesso, ele deverá então enviar as informações do cliente para https://controller_server_ip:https_port/extportal/site_name/auth?token=CSRFToken utilizando o método POST. Os dados de informação podem ser representados em formato JSON e devem conter os seguintes parâmetros “cid=client_mac&ap=ap_mac&ssid=ssid_name&t=time_since_epoch&rid=Radio_id&site=site_name&time=expire_time”.
Por exemplo,
private static function authorize($cid,$ap,$ssid,$rid,$t,$seconds,$site)
{
// Enviar usuário para autorização e o tempo permitido
$authInfo = array(
'cid' => $cid,
'ap' => $ap,
'ssid' => $ssid,
'rid' => $rid,
't' => $t,
'time' => $seconds
);
$ch = curl_init();
// post
curl_setopt($ch, CURLOPT_POST, TRUE);
// Definir retorno como valor, não retornar para a página
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Configurar cookies
curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE_FILE_PATH);
curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE_FILE_PATH);
// Permitir certificados autoassinados
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// Chamada da API
$csrfToken = self::getCSRFToken();
curl_setopt($ch, CURLOPT_URL, CONTROLLER_SERVER ."/extportal/". $site."/auth"."?token=".$csrfToken);
$data = json_encode($authInfo);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($authInfo));
$res = curl_exec($ch);
$resObj = self::resultConvert($res);
if($resObj['success'] == false){
echo $res;
}
curl_close($ch);
}
private static function resultConvert($json)
{
$json = str_replace(array('{','}',':',','),array('[{" ',' }]','":',',"'),$json);
function cb_quote($v)
{
return '"'.trim($v[1]).'"';
}
$newJSON=preg_replace_callback("~\"(.*?)\"~","cb_quote", $json);
$res = json_decode($newJSON, true)[0];
return $res;
}
private static function getCSRFToken(){
$myfile = fopen(TOKEN_FILE_PATH, "r") or die("Não foi possível abrir o arquivo!");
$token = fgets($myfile);
fclose($myfile);
return $token;
}
(Etapa 11)
O significado desses parâmetros é o mesmo apresentado na Tabela 1 – Explicação dos parâmetros. O parâmetro time aqui representa o número de segundos antes que a autenticação do cliente expire. Esse parâmetro é definido pelo servidor de portal.
9. O Omada Controller retorna uma mensagem em JSON: {"success": [true/false], "message":"informação de retorno"} ao servidor de portal após processar as informações fornecidas na requisição HTTP POST. A forma como o servidor de portal lida com a mensagem JSON depende da sua própria implementação. Por fim, o servidor de portal deve fazer logout do Omada Controller enviando uma requisição POST para https://controller_server_ip:https_port/logout?token=CSRFToken.
Por exemplo
private static function logout()
{
$ch = curl_init();
// Post
curl_setopt($ch, CURLOPT_POST, TRUE);
// Definir retorno como valor, não retornar para a página
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Configurar cookies
curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE_FILE_PATH);
curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE_FILE_PATH);
// Permitir certificados autoassinados
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// Chamada da API
$csrfToken = self::getCSRFToken();
curl_setopt($ch, CURLOPT_URL, CONTROLLER_SERVER . "/logout"."?token=".$csrfToken);
curl_exec($ch);
curl_close($ch);
}
(Etapa 12 e Etapa 13)
TOKEN_FILE_PATH é um arquivo que armazena o CSRFToken retornado pela requisição de login; os clientes podem configurá-lo conforme necessário.
Nota: Para chamar a API com sucesso, o seu servidor de portal deve ser configurado para atender aos dois pontos a seguir:
1. Permitir certificado autoassinado;
2. Ler os pacotes HTTPS do servidor, salvar o TPEAP_SESSIONID no Cookie,e utilizar esse cookie nas requisições futuras.