用php寫wifidog的認證服務器

路由器上wifidog的設置

圖片描述

主要設置鑑權服務器主機名(域名或ip均可以)和加粗鑑權服務器路徑php

路由器會請求如下四個地址:html

http://認證服務器/路徑/login
http://認證服務器/路徑/auth
http://認證服務器/路徑/ping
http://認證服務器/路徑/portal
http://認證服務器/路徑/gw_message.phpmysql

因此咱們須要每一個請求創建一個文件夾下一個index.phpsql

預備知識

客戶端首次鏈接wifi,瀏覽器請求將被重定向到login並攜帶參數數據庫

login/?gw_address=路由器ip&gw_port=路由器wifidog的端口&gw_id=用戶id&url=被重定向前用戶瀏覽的地址segmentfault

(2013版本的wifidog參數多了mac)瀏覽器

而login/index.php須要作的就是驗證經過後再重定向到網關:服務器

http://網關地址:網關端口/wifidog/auth?token=session

以後wifidog會啓動一個線程週期性報告用戶狀態:post

/auth?stage=&ip=&mac=&token=&incoming=&outgoing=

/auth/index.php則須要返回是否讓該用戶繼續上網,回覆格式:Auth:狀態碼(0:拒絕, 1:驗證經過)

驗證成功後,路由器將請求/portal/?gw_id=%s

在/portal/index.php就能夠寫重定向到第一次請求的url參數或者重定向到自定義網址了

/ping/index.php的做用就是告訴路由器認證服務器尚未崩
/gw_message/index.php做用是當認證過程出現錯誤的時候,想用戶顯示錯誤信息

開工

咱們將完成用戶用帳號密碼方式認證

1.首次重定向:

/login/index.php

<?php
//獲取url傳遞過來的參數
parse_str($_SERVER['QUERY_STRING'], $parseUrl);
//gw_address、gw_port、gw_id是必需參數,缺乏不能認證成功.
if( !array_key_exists('gw_address', $parseUrl) || !array_key_exists('gw_port', $parseUrl) || !array_key_exists('gw_id', $parseUrl)){
    exit;
}
//若是提交了帳號密碼
if(isset($_POST['name']) && isset($_POST['password'])){
    $username = $_POST['name'];
    $password = $_POST['password'];
    $db = new mysqli('localhost', 'root', '', 'test');
    if(mysqli_connect_errno()){
        echo mysqli_connect_error();
        die;
    }
    $db->query("set names 'utf8'");
    $result = $db->query("SELECT * FROM user WHERE username='{$username}' AND password='{$password}'");
    if($result && $result->num_rows != 0){
        //數據庫驗證成功
        $token = '';
        $pattern="1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ";
        for($i=0;$i<32;$i++)
            $token .= $pattern[ rand(0,35) ];
        //把token放到數據庫,用於後續驗證(auth/index.php)
        $time = time();
        $sql = "UPDATE user SET token='{$token}',logintime='{$time}'";
        $db->query($sql);
        $db->close();
        //登錄成功,跳轉到路由網管指定的頁面.
        $url = "http://{$parseUrl['gw_address']}:{$parseUrl['gw_port']}/wifidog/auth?token={$token}";
        header("Location: ".$url);
    }else{
        //認證失敗
        //直接重定向本頁 請求變成get
        $url='http://'.$_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"];
        header("Location: ".$url);
    }
}else{
    //get請求
    //一個簡單的表單頁面
    $html = <<< EOD
    <html>
        <head>
            <title>portal login</title>
        </head>
        <body>
            <form action="#" method="post">
            username:<input type="text" name="username" />
            password:<input type="password" name="password" />
            <input type="submit" value="submit" />
            </form>
        </body>
    </html>
EOD;
    echo $html;
}

2.用戶認證協議:

/auth/?stage=%s&ip=%s&mac=%s&token=%s&incoming=%s&outgoing=%s
參數解釋:
stage: 認證階段,就logoin和counters兩種
token: login頁面下發的token
incoming: 下載流量
outgoing: 上傳流量

/auth/index.php

<?php
//獲取url傳遞過來的參數
parse_str($_SERVER['QUERY_STRING'], $parseUrl);
//須要多少參數用戶可本身頂
if( !array_key_exists('token', $parseUrl) ){
    //拒絕
    echo "Auth:0";
    exit;
}

$db = new mysqli('localhost', 'root', '', 'test');
$db->query("set names 'utf8'");
$token = $parseUrl['token'];
$sql = "SELECT * FROM user WHERE token='{$token}'";
$result = $db->query($sql);
if($result && $result->num_rows != 0){
    //token匹配,驗證經過
    echo "Auth:1";
}else{
    echo "Auth:0";
}

3.Ping協議

/ping/?gw_id=%s&sys_uptime=%lu&sys_memfree=%u&sys_load=%.2f&wifidog_uptime=%lu

wifidog會向認證服務器發送一些信息,來報告wifidog如今的狀況,這些信息是經過Http協議發送的,如上的連接所示,參數大概如字面意思,沒仔細研究過,而做爲認證服務器,auth_server應迴應一個"Pong"。
主要做用是路由確認認證服務器仍然存活,沒有死機,另一個功能是認證服務器能夠收集路由的負載等的信息。路由器會定時訪問這個腳本,腳本必須回覆Pong,不然將認爲認證服務器失效而出錯。

/ping/index.php

<?php
echo "Pong";
?>

4.認證成功後的跳轉

portal/?gw_id=%s

在認證成功後,wifidog會將用戶重定向至該頁面。

/portal/index.php

<?php
//認證前用戶訪問任意url,而後被重定向登陸頁面,session記錄的是這個「任意url」.
$url = $_SESSION["url"];//若是login參數url保存到session中
//跳轉到登錄前頁面.
header("Location: ".$url);

5.若驗證失敗,則會根據失敗緣由跳轉至以下頁面

gw_message.php?message=denied

gw_message.php?message=activate

gw_message.php?message=failed_validation

/gw_message.php

<?php
    $message = null;
    if(isset($_GET["message"])){
        $message = $_GET["message"];
    }
    echo $message;
?>

總結

wifidog的認證流程是:

  1. 用戶連上wifi,發起一個訪問網站的請求,如:segmentfault.com

  2. 網關根據防火牆規則,將請求重定向本地(路由器的ip)的wifidog端口

  3. wifidog重定向到認證服務器的認證頁面

  4. 認證服務器返回登陸頁面讓用戶填寫

  5. 用戶填寫後請求認證

  6. 認證服務器根據用戶提供數據肯定是否符合要求

  7. 若是符合要求,認證服務器將用戶重定向路由器網關並攜帶token

  8. 網關向認證服務器肯定用戶信息

  9. 若是符合要求,服務器返回用戶登陸成功的頁面

  10. 用戶正常上網

相關文章
相關標籤/搜索