php单点登录之模拟淘宝天猫同步登录

时间:2024-04-15 16:47:02

说到单点登录大家都很了解,一个站点登录其他域会自动登录。

单点登录SSO(Single Sign On)的方法有很多,比如:p3p、共享session、共享cookice、第三方OAuth认证。

这里模拟淘宝、天猫登录。是模拟噢,要做到安全就要进行很多安全验证RSA加密了,带签名的参数了等。

淘宝与天猫登录时都是在淘宝登录,登录后redirect跳转到各自的网站HTTP_REFERER。

本地模拟,MY淘宝:http://my-taobao.com:8080/      My天猫:http://my-tmall.com/

为什么本地模拟的时候要修改一个的默认端口80为8080或其他端口,参考:http://www.cnblogs.com/dcb3688/p/4608003.html

 

My淘宝有三个文件,分别是:index.php login.php 与api.php

index.php

<?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淘宝是否登录。