📄 advanced_passport.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Discuz! 用户使用说明书 - 高级应用</title><link rel="stylesheet" href="discuz_guide.css">
<base target="_blank">
</head>
<body leftmargin="0" rightmargin="0" topmargin="0">
<script language="JavaScript" src="header.js"></script>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr><td class="title">本栏目下相关链接</td></tr>
<tr><td><br><ul><script language="JavaScript" src="advanced.js"></script></ul><br></td></tr>
<tr><td class="title">Discuz! Passport 接口技术文档</td></tr>
<tr><td><br>
<p>从 Discuz! 4.0.0 RC4 版本开始,Discuz! 内嵌了一个独特的 Passport(通行证) 接口,利用此接口,用户将很容易将论坛与其他应用
程序整合,而实现统一登录与退出、用户数据共享、积分同步等功能。可以整合的应用程序包括内容管理系统(CMS)、商城系统、游戏系统等
等,如您对这方面功能有兴趣或有需求,请继续阅读本文档。
<p class="subtitle">Discuz! Passport 的优点
<ul>
<p>Discuz! Passport 系统使用了 Discuz! 独有的技术,并不等同于以往使用过的一些方法,与传统的实现方式相比,具备(不限于)以下优势:
<br><br><li>基于私有密匙的低相关性可逆加密算法,配合 MD5 校检码技术,使得暴力破解或伪造几乎不可能。
<li>应用程序可与论坛放置于不同的服务器及不同的域名下。可基于不同操作系统、不同程序语言和不同数据库平台,具备真正的平台无关性。
<li>不需要任何形式的数据库连接、或强制把两套应用程序的数据放在同一数据库甚至同一数据表中。论坛与应用程序都有各自的用户数据表,
只是在需要时进行无缝同步操作。
<li>对应用程序的代码改动简便易行,可最快速的完成应用程序与论坛间的整合。
</ul>
<p class="subtitle">Discuz! Passport 的局限
<ul>
<p>您在开始利用 Discuz! Passport 进行二次开发时,需要了解这个系统的局限性,以对未来的工作进行正确的评估与安排。
<br><br><li>只能工作在用户密码不加密、可逆加密或 MD5 加密的情况下,否则论坛后台无法登录。
<li>只能与一种应用程序关联,即二方关联。不能实现三方关联或与更多的应用程序进行关联。
<li>应用程序需具有独立的注册、登录、退出页面和链接,否则需要自行修改论坛中的相应表单或程序。
<li>由于论坛的注册人数可能很多,例如百万级以上,且应用程序和论坛间的用户数据是同步的,因此要求应用程序能够稳定的负载大量用户的
访问。
</ul>
<br></td></tr><tr><td class="title">Discuz! Passport 原理与流程</td></tr>
<tr><td><br>
<p class="subtitle">假设已设置如下变量或参数
<p><ul>
<li>挂接 Discuz! Passport 的应用程序假设为一套 PHP 语言编写的 CMS 系统
<li>Discuz! 的 URL 为 http://www.myforums.com
<li>应用程序的 URL 为 http://www.mywebsite.com
<li>应用程序的注册页面为 http://www.mywebsite.com/register.php
<li>应用程序的登录页面为 http://www.mywebsite.com/login.php?action=login
<li>应用程序的退出页面为 http://www.mywebsite.com/login.php?action=logout
</ul>
<p class="subtitle">开启通行证后的用户登录流程
<p><ul type="1">
<li>如果用户在论坛点击“登录”,则转向到事先设置好的应用程序登录页面(http://www.mywebsite.com/login.php?action=login),并在登录页面
的 URL 中加入参数 forward(加入 forward 后的链接例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),
用于在登录后将用户导向到指定的 URL。
<br><br><li>应用程序收到此请求后,按照惯例生成表单,并<u>增加一个表单变量 <input type="hidden" name="forward" value="<?=htmlspecialchars($_GET['forward'])?>">,
将 GET 方式传递过来的 forward 参数通过表单进行传递。</u>
<br><br><li>用户在应用程序的表单中填写登录信息,并提交到应用程序的登录验证程序。应用程序验证用户提交的用户名和密码的合法性:
<ul>
<br><li>如果不通过:提示用户名密码错误,要求其返回上一页重新填写。
<br><br><li>如果通过,需要进行如下操作:
<ul>
<br><li>设置自身 Cookie 或 Session,使得应用程序自身处于登录状态。
<br><br><li><u>检查表单中是否提交了 forward 变量,如有,则意味着登录请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward
变量,使得论坛登录后能够跳转回到应用程序中。</u>
<br><br><li><u>通过 header('Location: http://www.myforums.com/api/passport.php?action=login&auth=xxx&forward=http://yyy&verify=zzz') 的
方式,将登录请求传递到论坛进行处理。其中 auth 用来将用户信息与资料以特定的格式,加密传递给论坛,forward 用于告知论坛 Passport API 完成
自身操作后转向到的 URL 地址,verify 用于验证前面两个变量的有效性。auth、forward、verify 格式与结构将在后面进行说明。</u>
</ul>
</ul>
<br><br><li>Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
<ul>
<br><li>根据 verify 判断 auth 和 forward 变量是否合法,如合法则继续,否则终止。
<br><br><li>将 auth 根据既定算法解密,并还原成数组,数组的内容与格式将在后面进行说明。根据数组中的内容,检查此用户是否存在。如存在,则根据
上述数组中的内容 UPDATE 论坛中相应的用户资料。如不存在,则使用数组中的信息 INSERT 到论坛用户资料表中。
<br><br><li>论坛设置 Cookie 或 Session,使得论坛自身处于登录状态。
<br><br><li>根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。
</ul>
<br><br><li>至此,登录流程结束
</ul><p class="subtitle">开启通行证后的用户退出流程
<p><ul type="1">
<li>如果用户在论坛点击“退出”,则转向到事先设置好的应用程序退出页面(http://www.mywebsite.com/login.php?action=logout),并在登录页面
的 URL 中加入参数 forward(例如 http://www.mywebsite.com/login.php?action=login&forward=http://www.myforums.com/index.php),用于
在退出后将用户导向到指定的 URL。
<br><br><li>应用程序收到此请求后,清除自身 Cookie 或 Session,使得应用程序自身处于非登录状态。
<br><br><li><u>检查是否提交了 forward 变量,如有,则意味着登录请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward
变量,使得论坛登录后能够跳转回到应用程序中</u>。
<br><br><li><u>通过 header('Location: http://www.myforums.com/api/passport.php?action=logout&forward=http://yyy&verify=zzz') 的方式,将
退出请求传递到论坛进行处理。其中 forward 用于告知论坛 Passport API 完成自身操作后转向到的 URL 地址,verify 用于验证 forward 变量的
有效性。forward、verify 格式与结构将在后面进行说明</u>。
<br><br><li>Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
<ul>
<br><li>根据 verify 判断 forward 变量是否合法,如合法则继续,否则终止。
<br><br><li>清楚论坛的 Cookie 或 Session,使得论坛自身处于非登录状态。
<br><br><li>根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。
</ul>
<br><br><li>至此,退出流程结束。
</ul><p class="subtitle">开启通行证后的用户注册流程
<p><ul type="1">
<li>如果用户在论坛点击“注册”,则转向到事先设置好的应用程序注册页面(http://www.mywebsite.com/register.php),并在注册页面的 URL 中
加入参数 forward(例如 http://www.mywebsite.com/register.php?forward=http://www.myforums.com/index.php),用于在注册后将用户导向到
指定的 URL
<br><br><li>应用程序收到此请求后,按照惯例生成表单,并<u>增加一个表单变量 <input type="hidden" name="forward" value="<?=htmlspecialchars($_GET['forward'])?>">,
将 GET 方式传递过来的 forward 参数通过表单进行传递</u>
<br><br><li>用户在应用程序的表单中填写注册信息,并提交到应用程序的注册验证程序。应用程序验证用户提交信息的完整性和合法性:
<ul>
<br><li>如果不通过:提示其问题所在,要求其返回上一页重新填写
<br><br><li>如果通过,需要进行如下操作:
<ul>
<br><li>将用户资料插入到应用程序自身用户数据库中
<br><br><li>设置自身 Cookie 或 Session,使得应用程序自身处于登录状态
<br><br><li><u>检查表单中是否提交了 forward 变量,如有,则意味着注册请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward
变量,使得论坛注册后能够跳转回到应用程序中</u>
<br><br><li><u>通过 header('Location: http://www.myforums.com/api/passport.php?action=login&auth=xxx&forward=http://yyy&verify=zzz') 的
方式,将注册请求传递到论坛进行处理。其中 auth 用来将用户信息与资料以特定的格式,加密传递给论坛,forward 用于告知论坛 Passport API 完成
自身操作后转向到的 URL 地址,verify 用于验证前面两个变量的有效性。auth、forward、verify 格式与结构将在后面进行说明</u>
</ul>
</ul>
<br><br><li>Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
<ul>
<br><li>根据 verify 判断 auth 和 forward 变量是否合法,如合法则继续,否则终止
<br><br><li>将 auth 根据既定算法解密,并还原成数组,数组的内容与格式将在后面进行说明。根据数组中的内容,检查此用户是否存在。如存在,则根据
上述数组中的内容 UPDATE 论坛中相应的用户资料。如不存在,则使用数组中的信息 INSERT 到论坛用户资料表中
<br><br><li>论坛设置 Cookie 或 Session,使得论坛自身处于登录状态
<br><br><li>根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL
</ul>
<br><br><li>至此,注册流程结束
<p><b>本部分中,加下划线显示的部分,是需要对您的应用程序进行更改的部分,事实上,这部分更改会非常容易和方便。</b>
</ul><br></td></tr><tr><td class="title">Discuz! Passport 参数规格与加密方式</td></tr>
<tr><td><br>
<p class="subtitle">私有密匙(passport_key)
<ul><p>由于一些关键参数采用了 GET 方式进行传递,即便两次 header 跳转并不会直接将链接显示在外面,但我们仍然对关键的参数进行了加密,私有
密匙共有两个作用:其一是供下面提到的可逆加密算法(AzDGCrypt)进行数据的加解密。其二是生成不可逆验证字串(verify),以防止关键信息被
伪造。
<p>在启用 Discuz! Passort 后,您需要在应用程序和 Discuz! 后台配置两处私有密匙,这两处的内容必须完全相同,这样应用程序和论坛之间才能
正常通信。私有密匙决定了加密算法的强度,因此密匙长度请不要小于 10 个字节,并包含字母、数字和符号,以保证系统的安全。
</ul><p class="subtitle">加密算法
<ul><p>Discuz! Passport 采用 Azerbaijan Development Group(AzDG)开发的可逆加密算法 AzDGCrypt 对用户资料进行加密。如提供正确的私有密匙,
可通过本加密算法对数据进行加密及解密,因此只要保证私有密匙的保密性,即可确保数据传递过程中的安全。以下为 Discuz! Passport 中应用到
的可逆加密算法,为了生成可以被 Discuz! Passport 正确解密的 auth 字串,需要将如下函数放置于应用程序中,并可在登录及注册时调用。
<p>passport_encrypt()是加密函数,用法为 passport_encrypt($txt, $key),其中 $txt 是待加密的字串,$key 是私有密匙。<br>
passport_decrypt()是解密函数,用法为 passport_decrypt($txt, $key),其中 $txt 是加密后的字串,$key 是私有密匙。
<br><br><table width="80%" cellpadding="0" cellspacing="0" border="0" class="code">
<tr><td><pre>
/**
* Passport 加密函数
*
* @param string 等待加密的原字串
* @param string 私有密匙(用于解密和加密)
*
* @return string 原字串经过私有密匙加密后的结果
*/
function passport_encrypt($txt, $key) {
// 使用随机数发生器产生 0~32000 的值并 MD5()
srand((double)microtime() * 1000000);
$encrypt_key = md5(rand(0, 32000));
// 变量初始化
$ctr = 0;
$tmp = '';
// for 循环,$i 为从 0 开始,到小于 $txt 字串长度的整数
for($i = 0; $i < strlen($txt); $i++) {
// 如果 $ctr = $encrypt_key 的长度,则 $ctr 清零
$ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
// $tmp 字串在末尾增加两位,其第一位内容为 $encrypt_key 的第 $ctr 位,
// 第二位内容为 $txt 的第 $i 位与 $encrypt_key 的 $ctr 位取异或。然后 $ctr = $ctr + 1
$tmp .= $encrypt_key[$ctr].($txt[$i] ^ $encrypt_key[$ctr++]);
}
// 返回结果,结果为 passport_key() 函数返回值的 base65 编码结果
return base64_encode(passport_key($tmp, $key));
}
/**
* Passport 解密函数
*
* @param string 加密后的字串
* @param string 私有密匙(用于解密和加密)
*
* @return string 字串经过私有密匙解密后的结果
*/
function passport_decrypt($txt, $key) {
// $txt 的结果为加密后的字串经过 base64 解码,然后与私有密匙一起,
// 经过 passport_key() 函数处理后的返回值
$txt = passport_key(base64_decode($txt), $key);
// 变量初始化
$tmp = '';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -