php單點登陸之模擬淘寶天貓同步登陸

說到單點登陸你們都很瞭解,一個站點登陸其餘域會自動登陸。javascript

單點登陸SSO(Single Sign On)的方法有不少,好比:p3p、共享session、共享cookice、第三方OAuth認證。php

這裏模擬淘寶、天貓登陸。是模擬噢,要作到安全就要進行不少安全驗證RSA加密了,帶簽名的參數了等。html

淘寶與天貓登陸時都是在淘寶登陸,登陸後redirect跳轉到各自的網站HTTP_REFERER。java

本地模擬,MY淘寶:http://my-taobao.com:8080/      My天貓:http://my-tmall.com/node

爲何本地模擬的時候要修改一個的默認端口80爲8080或其餘端口,參考:http://www.cnblogs.com/dcb3688/p/4608003.htmljquery

 

My淘寶有三個文件,分別是:index.php login.php 與api.phpjson

index.phpapi

<?php
session_start();
$session_name=  isset($_SESSION['name'])?$_SESSION['name']:'';
$session_token=  isset($_SESSION['token'])?$_SESSION['token']:'';

if($session_name){
     echo "<strong>{$session_name}</strong>您已登陸My-Taobao.com &nbsp; <a href='/api.php?action=logout&token={$session_token}'>退出</a>";
}else{
     echo "您還未登陸My-Taobao.com &nbsp; <a href='/login.php'>登陸</a>";
}

 

login.php瀏覽器

<meta charset="utf-8"/>
<form action="api.php" method="post">
    <input type="text" name="name">
    <input type="hidden" name="action" value="login">
    <input type="hidden" name="redirect" value="<?php echo $_SERVER['HTTP_REFERER'] ?>">
    <input type="submit">
</form>
<?php

session_start();
$session = isset($_SESSION['token']) ? $_SESSION['token'] : '';
$redirect = isset($_REQUEST['redirect']) ? $_REQUEST['redirect'] : "/";
$action = isset($_POST['action']) ? $_POST['action'] : '';
/**
 * post 登陸
 */
if ($action == 'login') {
    if ($session) {  #已是登陸的狀態
        echo '<meta charset="UTF-8"><script type="text/javascript">window.location.href = "' . $redirect . '";</script>';
    }
    $session = md5(time() . uniqid());
    $_SESSION['token'] = $session;
    $_SESSION['name'] = $_POST['name'];
    $_SESSION['create_time'] = time();

    if (!is_dir('session')) {
        mkdir('session');
    }
    $fopen = fopen('session/' . $_SESSION['token'], 'w+'); //新建文件命令
    fputs($fopen, serialize($_SESSION)); //向文件中寫入內容;
    fclose($fopen);

    exit('<meta charset="UTF-8"><script type="text/javascript">window.location.href = "' . $redirect . '";</script>');
}







/**
 * curl登陸驗證
 */
if ($action == 'curl_valid') {
    $token = isset($_POST['token']) ? $_POST['token'] : '';
    $res = 0;
    if ($token) {
        if (file_exists('session/' . $token)) { # 存在該文件
            $data = unserialize(file_get_contents('session/' . $token));
            if (isset($data['create_time'])) {
                if ($data['create_time'] > time() - 7200) {
                    $res = 1;
                }
            }
        } 
    }
    
    exit( json_encode(["status"=>$res]));
}

/**
 * get 退出
 */
$actionLogout = isset($_GET['action']) ? $_GET['action'] : '';
if ($actionLogout == 'logout') {
    if (isset($_GET['token'])) {
        unlink("session/".$_SESSION['token']);
        unset($_SESSION['token']);
        unset($_SESSION['name']);
    }
    exit('<script type="text/javascript">window.location.href = "' . $_SERVER['HTTP_REFERER'] . '";</script>');
}

/**
 * jsonp 訪問
 */
$jsonp = isset($_GET['jsonp_callback']) ? $_GET['jsonp_callback'] : '';
if ($jsonp) {
    $status = 0;
    $node = [];
    $msg = '';
    if (isset($_SESSION['token'])) {
        $status = 1;
        $msg = 'success';
        $node = $_SESSION;
    } else {
        $msg = 'fail';
    }
    exit($jsonp . '(' . json_encode(['status' => $status, 'msg' => $msg, 'node' => $node]) . ')');
}

 

 

My天貓有兩個文件: index.php 與 list.php安全

index.php

<span id="line">

</span>
<script src="http://yiiui.com/static/v1/JUI/js/jquery-1.7.2.min.js"></script>

<script >

    /**
     * 獲取cookie
     */
    function getCookie(cookiename) {
        var result;
        var mycookie = document.cookie;
        var start2 = mycookie.indexOf(cookiename + "=");
        if (start2 > -1) {
            start = mycookie.indexOf("=", start2) + 1;
            var end = mycookie.indexOf(";", start);

            if (end == -1) {
                end = mycookie.length;
            }
            result = unescape(mycookie.substring(start, end));
        }
        return result;
    }
    /**
     * 設置cookie
     */
    function setCookie(name, value) {
        var Days = 30;
        var exp = new Date();
        exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
        document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
    }

    var token = getCookie("token");


    if (token === null) { // 首次訪問my-tmall.com

        // php curl 不能獲取session由於curl是服務器端請求,jsonp是本地的客戶端請求。
        $.getJSON("http://my-taobao.com:8080/api.php?jsonp_callback=?", function (data) {
            if (data.status == 1) {
                data = data.node;
                setCookie('token', data.token);
                console.log(data);
                $("#line").html("<strong>" + data.name + "</strong>您已登陸My-Tmall.com &nbsp; <a href='http://my-taobao.com:8080/api.php?action=logout&token=" + data.token + "'>退出 </a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='list.php'>列表</a>");
            } else {
                $("#line").html("您還未登陸My-Tmall.com &nbsp; <a href='http://my-taobao.com:8080/login.php'>登陸</a>");
            }
        });
    } else { // 已經登陸過,查詢如今登陸狀態
        $.getJSON("http://my-taobao.com:8080/api.php?jsonp_callback=?", function (data) {
            if (data.status == 1) {  // 登陸
                data = data.node;
                if (data.token != token) {  // 登錄其餘帳戶了
                    setCookie('token', data.token);
                    window.location.href = document.location.href;
                } else {
                    $("#line").html("<strong>" + data.name + "</strong>您已登陸My-Tmall.com &nbsp; <a href='http://my-taobao.com:8080/api.php?action=logout&token=" + data.token + "'>退出</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='list.php'>列表</a>");
                }
            } else { // 未登陸 
                $("#line").html("您還未登陸My-Tmall.com &nbsp; <a href='http://my-taobao.com:8080/login.php'>登陸</a>");
            }
        });
    }




</script>

 

list.php

<?php

$token = isset($_COOKIE["token"]) ? $_COOKIE["token"] : '';
//print_r($token);

$curl = curl(["action" => 'curl_valid', "token" => $token], "http://my-taobao.com:8080/api.php");
$ac = json_decode($curl, TRUE);

if (isset($ac['status']) && $ac['status'] == 1) { # 登陸中
    echo '<ul>'
    . '<li>1111</li>'
    . '<li>2222</li>'
    . '<li>3333</li>'
    . '<li>4444</li>'
    . '<li>5555</li>'
    . '</ul>';
} else {
    echo '已退出';
}

function curl($data, $url, $method = 'POST', $headers = array()) {
    $ch = curl_init();
    $method_upper = strtoupper($method);
    if ($method_upper == 'POST') {
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    } else {
        $url = $url . (strpos($url, '?') ? '&' : '?') . (is_array($data) ? http_build_query($data) : $data);
        curl_setopt($ch, CURLOPT_URL, $url);
    }
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method_upper);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);    //SSL 報錯時使用
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);    //SSL 報錯時使用
    if ($headers) {
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    $tmpInfo = curl_exec($ch);
    if (curl_errno($ch)) {
        exit(curl_error($ch));
    }
    curl_close($ch);
    return $tmpInfo;
}

 

很簡單的原理,My淘寶是正常網站登陸與註銷(主站)。當任何一個網站登陸且訪問My天貓,My天貓就Jsonp請求當前瀏覽器中是否登陸過MY淘寶。若是登陸過就種下一個cookice保存MY淘寶sessionKey。

當要訪問My天貓其餘頁面的時候可直接經過獲取Cookice使用php的CURL請求網站MY淘寶是否登陸。

相關文章
相關標籤/搜索