SSO单点登录-简单实现

 一、二级域名之间的单点登录

不需要用到JSONP 或者 p3p 协议,直接使用 COOKIE 就行了,因为顶级域名相同就能实现 COOKIE 共享。

例如有两个项目,域名分别是 www.site1.com 和 mall.site1.com,分别对应的项目目录是 /site1/p3p 和 /site1_origin

site1 的登陆页面 /site1/p3p/login.php

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>site1-login</title>
</head>
<?php 

header(‘content-type:text/html;charset=utf-8‘);
session_start();

$user = isset($_SESSION[‘username‘]) ? $_SESSION[‘username‘] : ‘游客‘;
echo ‘你好, ‘.$user;
if($user != ‘游客‘) {
    echo ‘ | <a href="logout.php">退出</a><br /><br />‘;
} else {
    echo ‘<br /><br />‘;
}

?>
<body>
    <form action="" method="post">
        <table>
            <tr>
                <td>登录名:</td>
                <td><input type="input" name="username"></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="登陆"></td>
            </tr>
        </table>
    </form>
</body>
</html>

<?php

if(isset($_POST[‘username‘])) {

    $username = htmlentities($_POST[‘username‘]);
    $password = md5(htmlentities($_POST[‘password‘]));

    // 设置同域 COOKIE
    setcookie(‘username‘, $username, time() + 3600, ‘/‘, ‘site1.com‘);
    $_SESSION[‘username‘] = $username;

?>
<script>window.location = "index.php";</script>
<?php
}
?>

通过 setcookie() 的第五个参数来设置 COOKIE 域,当设置为 ‘site1.com‘ 时,在 www.site1.com 和 mall.site1.com 中同时会生成 COOKIE。

mall.site1.com 的 index.php 页面用于查看 COOKIE:

<?php

header(‘content-type:text/html;charset=utf-8‘);
session_start();

if(isset($_COOKIE[‘username‘])) {

    $user = $_COOKIE[‘username‘];
    $_SESSION[‘username‘] = $user;

} else {
    $user = ‘游客‘;
}

echo ‘你好, ‘.$user;

回到顶部

二、跨域的单点登录

例如有四个项目,域名分别是 www.site1.com 、mall.site1.com、www.site2.com、www.sso.com,分别对应的项目目录是 /site1/p3p 、 /site1_origin、/site2/p3p、/sso

如图:

www.site1.com 和 www.site2.com 是两个不同的域,mall.site1.com 是 site1.com 的一个二级域名,www.sso.com 是处理 sso 单点登录单独设置的一个服务。

原理是当用户在 www.site1.com 或 www.site2.com 进行登陆或者注销时,生成相应的参数,并且重定向到 www.sso.com 对所有相关的站点借助 <script> 发送 HTTP 请求,添加或者删除 COOKIE,以达到同时登陆同时注销的目的,再跳转回原站点。

site1 的登录页面 /site1/p3p/login.php:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>site1-login</title>
</head>
<?php 

header(‘content-type:text/html;charset=utf-8‘);
session_start();

$user = isset($_SESSION[‘username‘]) ? $_SESSION[‘username‘] : ‘游客‘;
$welcome = $user == ‘游客‘ ? $user : ‘<a href="index.php">‘.$user.‘</a>‘;
echo ‘你好, ‘.$welcome;
if($user != ‘游客‘) {
    echo ‘ | <a href="logout.php">退出</a><br /><br />‘;
} else {
    echo ‘<br /><br />‘;
}

?>
<body>
    <form action="" method="post">
        <table>
            <tr>
                <td>登录名:</td>
                <td><input type="input" name="username"></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="登陆"></td>
            </tr>
        </table>
    </form>
</body>
</html>

<?php

if(isset($_POST[‘username‘])) {

    $username = htmlentities($_POST[‘username‘]);
    $password = md5(htmlentities($_POST[‘password‘]));

    // 设置同域 COOKIE
    setcookie(‘username‘, $username, time() + 3600, ‘/‘, ‘site1.com‘);
    $_SESSION[‘username‘] = $username;

    $salt = ‘sso_example_‘.strtotime(date(‘Y-m-d H‘));
    $token = md5($salt);

    // 跳转
    header("Location:http://www.sso.com/set_cookie.php?username=$username&token=$token&from=".urlencode(‘http://‘.$_SERVER[‘SERVER_NAME‘])."&operate=1");
}
?>

当 operate 为 1 时为登陆,为 2 时为注销。

site1 的 COOKIE 处理页面 /site1/p3p/set_cookie.php

<?php
session_start();

$salt = ‘sso_example_‘.strtotime(date(‘Y-m-d H‘));

if($_GET[‘token‘] == md5($salt) && isset($_GET[‘username‘]) && $_GET[‘username‘] != ‘‘) {

     // 添加 SESSION
    if(1 == $_GET[‘operate‘]) {

        $username = trim(htmlentities($_GET[‘username‘]));
        $_SESSION[‘username‘] = $username;
        setcookie(‘username‘, $username, time() + 3600, ‘/‘, ‘site1.com‘);
    } else {

        // 删除 SESSION
        session_unset();
        session_destroy();
        // 删除 COOKIE
        setcookie(‘username‘, false, time() - 1, ‘/‘, ‘site1.com‘);
        if(isset($_COOKIE[session_name()])) {
            setcookie(session_name(), ‘‘, time() - 1, ‘/‘, ‘site1.com‘);
        }
    }
}

site1 的注销页面 site1/p3p/logout.php

<?php
header(‘content-type:text/html;charset=utf-8‘);

session_start();
session_unset();
session_destroy();

$salt = ‘sso_example_‘.strtotime(date(‘Y-m-d H‘));
$token = md5($salt);

$username = $_COOKIE[‘username‘];

if(isset($_COOKIE[session_name()])) {
    setcookie(session_name(), ‘‘, time() - 1, ‘/‘, ‘site1.com‘);
}
setcookie(‘username‘, false, time() - 1, ‘/‘, ‘site1.com‘);
echo ‘退出成功‘;

// 跳转
header("Location:http://www.sso.com/set_cookie.php?username=$username&token=$token&from=".urlencode(‘http://‘.$_SERVER[‘SERVER_NAME‘])."&operate=2");
?>

site1 的主页,用于显示用户的登陆情况 /site1/p3p/index.php

<?php

header(‘content-type:text/html;charset=utf-8‘);
session_start();

if(isset($_COOKIE[‘username‘])) {

    $user = $_COOKIE[‘username‘];
    $_SESSION[‘username‘] = $user;

} else {
    $user = ‘游客‘;
}

echo ‘你好, ‘.$user;

if($user != ‘游客‘) {
    echo ‘ | <a href="login.php">返回登录页</a>‘;
    echo ‘ | <a href="logout.php">退出</a>‘;
} else {
    echo ‘ | <a href="login.php">登陆</a>‘;
}

mll.site1.com 的主页,查看用户登录或者注销情况 /site1_origin/index.php

<?php

header(‘content-type:text/html;charset=utf-8‘);
session_start();

if(isset($_COOKIE[‘username‘])) {

    $user = $_COOKIE[‘username‘];
    $_SESSION[‘username‘] = $user;

} else {
    $user = ‘游客‘;
}

echo ‘你好, ‘.$user;

-------------------------------------------------------------------------------------

www.sso.com 借助 script 标签对所有站点发出 HTTP 请求。/sso/set_cookie.php

<?php

$username = trim(htmlentities($_GET[‘username‘]));
$token = $_GET[‘token‘];
$from = $_GET[‘from‘];
$operate = $_GET[‘operate‘];

// 同时登陆、注销的站点
$web_sites = array(‘www.site1.com‘, ‘www.site2.com‘);

foreach($web_sites as $sites) {
?>

<script src="http://<?php echo $sites;?>/p3p/set_cookie.php?username=<?php echo $username;?>&token=<?php echo $token;?>&from=<?php echo urlencode($from);?>&operate=<?php echo $operate;?>"></script>

<?php
}
$from = urldecode($from);
?>

<script>
    window.location = "<?php echo $from;?>/p3p/<?php if(1 == $operate) { echo ‘index.php‘;}else { echo ‘login.php‘;} ?>";
</script>

----------------------------------------------------------------------------------

site2 登陆页面 /site2/p3p/login.php

 www.site2.com/p3p/login.php

site2 注销页面 /site2/p3p/logout.php

 www.site2.com/p3p/logout.php

site2 COOKIE 处理页面 /site2/p3p/set_cookie.php

 set_cookie

site2 主页 /site2/p3p/index.php

 www.site2.com/p3p/index.php

---------------------------------------------------

图示:

① 从 www.site1.com 登陆

② 登陆后抓包:

③ 查看 mall.site1.com

④ 查看 www.site2.com

⑤ 从 www.site1.com 退出登录:

同时查看 mall.site1.com:

和 www.site2.com

==================================

附:

P3P 协议(Platform for Privacy Preference,隐私偏好设定平台),通过 p3p 协议也可以实现单点登录。

如果使用 P3P 协议实现 SSO 单点登录,可以在上面的代码中进行修改:首先设置 COOKIE 不再是各个站点的 set_cookie.php (例如:www.site1.com/p3p/set_cookie.php 或 www.site2.com/p3p/set_cookie.php),而是转移到 www.sso.com/set_cookie.php 中进行,经过验证之后设置所有相关站点的 COOKIE。由于是跨域设置 COOKIE,因此,在 www.sso.com/set_cookie.php 中应该加上:

header(‘P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"‘);

原文地址:https://www.cnblogs.com/cjymuyang/p/9662460.html

时间: 2024-07-31 20:30:30

SSO单点登录-简单实现的相关文章

SSO单点登录原理及实现

1.SSO分类 根据实现的域不同,可以把SSO分为同域SSO.同父域SSO.跨域SSO三种类型. 2.SSO实现原理 a.打开统一的登录界面 b.登录,同时向服务器写入Cookie c.进入其他应用 d.判断是否有对应的Cookie 如果没有则进入统一的登录界面 如果有则进入下一步验证 e.服务器验证Cookie的有效性 如果有效则进入下一步 如果无效则打开统一的登录界面 f.成功进入应用页面 3.同域SSO的实现 a.定义一个公共的登录页面 登录页面是通过访问不同路径的action跳转而来.

CAS实现SSO单点登录原理

1.      CAS 简介 1.1.  What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(属于 Web SSO ). CAS 开始于 2001 年, 并在 2004 年 12 月正式成为 JA-SIG 的一个项目. 1.2.  主要特性 1.   开源的.多协议的 SSO 解决方案: Protocols : Custom Protoc

SSO单点登录三种情况的实现方式详解

单点登录(SSO——Single Sign On)对于我们来说已经不陌生了.对于大型系统来说使用单点登录可以减少用户很多的麻烦.就拿百度来说吧,百度下面有很多的子系统——百度经验.百度知道.百度文库等等,如果我们使用这些系统的时候,每一个系统都需要我们输入用户名和密码登录一次的话,我相信用户体验肯定会直线下降.当然,对于个人博客这类系统来说根本就用不上单点登录了. 假如,我们的系统很庞大,但是就是这一个系统,并没有什么子系统.这时我们也不需要单点登录.我们需要的是搭建集群环境,这里虽说只有一个系

ofbiz SSO 单点登录

 1.ofbiz单点登录介绍 ofbiz点单登录是集成了CAS SSO,LDAP使用的,具体的CAS与LDAP怎么应用,在这里不做介绍. 2.ofbiz点单登录文档 ofbiz 12版本中,有英文的简单的ofbiz单点登录的问题. 路径在:apache-ofbiz-12.04.01\framework\documents\SingleSignOn.xml 3.ofbiz单点登录目录 ofbiz  单点登录集成的目录在:apache-ofbiz-12.04.01\specialpurpose\

CAS实现SSO单点登录原理(转)

1.      CAS 简介 1.1.  What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方法(属于 Web SSO ). CAS 开始于 2001 年, 并在 2004 年 12 月正式成为 JA-SIG 的一个项目. 1.2.  主要特性 1.   开源的.多协议的 SSO 解决方案: Protocols : Custom Protoc

spring+springmvc+Interceptor+jwt+redis实现sso单点登录

在分布式环境中,如何支持PC.APP(ios.android)等多端的会话共享,这也是所有公司都需要的解决方案,用传统的session方式来解决,我想已经out了,我们是否可以找一个通用的方案,比如用传统cas来实现多系统之间的sso单点登录或使用oauth的第三方登录方案? 今天给大家简单讲解一下使用spring拦截器Interceptor机制.jwt认证方式.redis分布式缓存实现sso单点登录 } publicvoid setUid(String uid) { this.uid = ui

spring cloud云架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)

上一篇我根据框架中OAuth2.0的使用总结,画了SSO单点登录之OAuth2.0 登出流程,今天我们看一下根据用户token获取yoghurt信息的流程: Java代码   /** * 根据token获取用户信息 * @param accessToken * @return * @throws Exception */ @RequestMapping(value = "/user/token/{accesstoken}", method = RequestMethod.GET) pu

Spring Cloud云架构 - SSO单点登录之OAuth2.0登录流程(2)

上一篇是站在巨人的肩膀上去研究OAuth2.0,也是为了快速帮助大家认识OAuth2.0,闲话少说,我根据框架中OAuth2.0的使用总结,画了一个简单的流程图(根据用户名+密码实现OAuth2.0的登录认证):  上面的图很清楚的描述了当前登录login的流程,现在我们针对于login做成相关的微服务,解析如下: 请求方式:POST服务URL: http://localhost:8080/user/login参数类型:application/jsonHeaders: Content-Type:

Spring Cloud云架构 SSO单点登录之OAuth2.0 根据token获取用户信息(4)

上一篇我根据框架中OAuth2.0的使用总结,画了SSO单点登录之OAuth2.0 登出流程,今天我们看一下根据用户token获取yoghurt信息的流程: /** * 根据token获取用户信息 * @param accessToken * @return * @throws Exception */ @RequestMapping(value = "/user/token/{accesstoken}", method = RequestMethod.GET) public Resp