关于奇矩互动奇矩互动招贤纳士奇矩互动优质虚拟主机Discuz!商业用户享有本站VIP服务LAMP环境配置手册(CentOS5.1)
发新话题
打印

Discuz! 二次开发相关

本主题由 Edwin 于 2008-5-20 10:54 加入精华

Discuz! 二次开发相关

Discuz! 插件的序言插件,是基于 Discuz! 论坛系统之上,设计开发的一种小程序或小方案,用来实现对论坛现有功能扩展和改进。由于 Discuz!已具有相当完备的底层架构,因此插件并不需要具备很多深层的设计思想,也不需要很专业的开发人员,只要把想实现的功能与论坛的基本体系挂接起来,论坛就能拥有更加个性化的功能。插件与界面风格都是实现论坛个性化的有效方式,前者多用于论坛功能和特性的扩充,后者则用来满足访问者多样化的审美取向。

Discuz!采用了标准的开发方式,为了方便程序员开发插件和用户安装使用插件,特别设计了一套完整的插件接口,为外挂型插件提供了一系列完善的支持。如果您是程序员,想为论坛实现某些附加功能,请仔细阅读插件设计和插件安装两部分的说明;如果您是论坛建立者,想使用他人开发好的插件模块,则只需阅读插件安装部分的说明。

Discuz! 的插件接口,从 3.1.2 版本开始提供至今,历经了数次版本升级,接口的体系越来越规范,功能也越来越丰富。目前4.0.0 版本使用的,是 Discuz!开发组依据以往经验和用户反馈,全面重新设计的一套接口规范,使得插件设计、发布、安装和使用都更加方便,同时与论坛结合的更紧密,有助于程序员把最大限度的精力投入到插件本身去,而无需考虑过多的挂接和兼容问题。

插件的实现通常分为两种形式:其一是没有自身程序,完全在现有 Discuz! 模板和代码基础上进行修改,这种插件又被叫做Hack,仅适用于插件和论坛本身功能有极密切的联系的情况,通常实现的功能较少,用以满足一部分特定的需求。这种方式需要使用者按照插件设计者提供的说明,手工修改代码,论坛升级时,往往兼容性不好,安装和升级都比较麻烦;其二是尽可能的使用外挂程序的方式,拥有相对独立而完整的功能,此种方式通常用来实现较多和较为复杂的论坛功能,可以通过 Discuz!插件接口实现傻瓜化的安装和配置,同时兼容性较好,安装和升级比较方便。有些插件的设计中,用上述两种形式都能实现,但我们仍然强烈推荐第二种方式,因为这会给方便更多的人安装和使用,降低了人工劳动的消耗,因此更会受到使用者的欢迎。

本文档主要对功能相对独立,使用外挂程序方式的插件的设计与使用作以说明。
真正的尊敬,既不属于那些批评别人头头是道的人,也不是属于给强人指出过错、指点别人哪里做的不好的人。真正的尊敬,是属于那些勇于亲身投入战场,脸上沾满了尘土、汗水和鲜血的奋斗者们。他们坚持不懈的努力,尽管曾经犯下错误,并一再失败,但他们满怀激情,执著不懈,将生命奉献于崇高的事业。他们为经过艰辛努力最终取得的伟大成就而自豪,如果失败,他们也败得荣耀。因此,那些既没赢得过胜利,也没懂得什么叫做失败的,冷漠、胆怯的灵魂,是永远也无法与这些真正值得尊敬的人相提并论的。
http://www.cnedwin.com

TOP

Discuz! 插件的安装

作为论坛软件的使用者,依托于 Discuz! 数量庞大的用户群体,您将可能获得丰富而多样的论坛插件。此类插件通常由第三方开发,其中大部分为免费提供的形式,在 Discuz! 现有功能的基础上,提供了更加个性化的选择。如果您热衷于为您的网友提供更加个性化的论坛服务,或把 DIY 您的论坛作为一项个人爱好,使用插件进行论坛扩充将会是很好的选择。但根据我们以往的经验,仍然发现用户在安装和使用插件中遇到了各种各样的问题,有些问题还相当棘手,而同时由于插件种类过于繁多,实现方法也大不相同,作为软件开发商,我们无法对插件的安装和使用提供技术支持,因此您使用插件的重要前提,是自身具有相当的经验和程序调试能力,以便在出现问题时妥善的解决,不至于影响到正常的论坛服务。

如果您是插件开发者,并希望公开发布您设计的论坛插件,也请仔细阅读本文档。更多的了解使用者的心态和感受,并将获得的经验应用于插件设计中去,将使您的插件受到更多使用者的欢迎和好评。
使用插件的风险

安装和使用插件无疑为使用者提供了令人兴奋的扩展特性,但您在动手之前必须要考虑清楚使用插件的风险,依据对风险的评估来决定是否安装插件,毕竟对于网站论坛来说,运行稳定和访问快速是压倒一切的根本目标。插件由第三方开发的性质,决定了插件的质量可能参差不齐,可能导致的问题有:

* 由于对系统权限控制的不精通和安全编码经验的不充足导致的论坛安全性下降,严重时插件可能会被作为攻击论坛系统、非法获取管理权限的入口;

* 并不是所有的插件作者和开发团队都深谙高效的编码技术和优化的数据结构设计,例如一条编写不当的 SQL 语句,可能会耗费比整个论坛系统更多的服务器资源。因此有些插件可能导致论坛变得不稳定、访问速度变慢、资源消耗提高;

* 由于 Discuz! 开发组长期坚持对论坛系统的功能及结构进行改进,以实现更优化的系统效率和更强大的系统功能。虽然采用插件接口推荐的设计方式,可以尽可能的避免兼容性问题,但由于插件实现方式的多样性,您使用的插件仍然有可能无法兼容于未来的 Discuz! 版本。通常适用于老版本的插件稍作修改就可以用于新版本 Discuz! 上,因此您需要等待插件开发团队提供专供新版本的插件升级包,或自行修改代码。某些情况下,因为模板和程序代码的升级,即便插件具有后续兼容性,您仍然需要重复修改插件用到的这些模板和代码,才能把插件挂接在新的版本上;

* 不少插件作者是属于兼职或个人爱好的性质,并不能坚持对插件提供升级和技术支持,因此您不能奢望插件作者一直帮助您解决使用插件的疑难问题,您自身良好的代码调试能力和丰富的 Web 应用程序开发使用经验,是使用论坛插件的必要保证。
安装插件的流程

如果您经过以上的风险评估,认为使用插件适合您当前的自身情况,就可以开始插件的安装了。如果插件基于 Discuz! 插件接口进行开发(请参考《插件设计》中的说明),则插件安装的流程就变得非常简单,可以按照如下的步骤进行:

* 下载所需的插件,仔细阅读插件说明书;

* 在 系统设置 的 插件管理中,将插件提供的导入代码粘贴到文本框中并提交;

* 按照插件说明书的描述,修改指定模板、程序,上传相应的插件文件到指定的目录;

* 按照插件说明书的描述,开启插件、设置插件参数并开始使用插件。

注意:上述步骤只是按照通用流程进行描述的,如果本文介绍的安装流程与插件说明书中的描述不符,请以插件提供者的描述为准。
真正的尊敬,既不属于那些批评别人头头是道的人,也不是属于给强人指出过错、指点别人哪里做的不好的人。真正的尊敬,是属于那些勇于亲身投入战场,脸上沾满了尘土、汗水和鲜血的奋斗者们。他们坚持不懈的努力,尽管曾经犯下错误,并一再失败,但他们满怀激情,执著不懈,将生命奉献于崇高的事业。他们为经过艰辛努力最终取得的伟大成就而自豪,如果失败,他们也败得荣耀。因此,那些既没赢得过胜利,也没懂得什么叫做失败的,冷漠、胆怯的灵魂,是永远也无法与这些真正值得尊敬的人相提并论的。
http://www.cnedwin.com

TOP

Discuz! 插件的设计

您在开始论坛插件的设计之前,有必要了解一下我们所推荐的插件设计方式,更好的规范性和兼容性,将使得您设计的插件受到更多使用者的欢迎,对于程序员而言,也有助于形成良好的编码习惯,实现自身能力的提升。如果您有意编写 Discuz! 论坛插件,请按照先后顺序仔细阅读本文档。

准备工作

插件实现流程

开始编写论坛插件,您应当首先对插件实现的流程有一个大致的了解,以下是我们推荐的插件编写流程:

  • 熟练使用 Discuz! 论坛系统后,对希望完善或补充的个性化功能进行评估,进而提出插件的功能需求。
  • 对插件做一个概括性的设计,例如:需要使用什么菜单、什么参数,配置哪些选项、数据结构如何设计、前后台实现哪些功能等等。
  • 阅读本文档并在系统设置中实际体验 Discuz! 插件接口所实现的功用,例如:您的插件应当如何设计才能良好的挂接到论坛系统中来。插件接口能够实现哪些功能、不能实现哪些功能,插件为此而需要做的优化、改造和取舍。
  • 编写相应程序代码和模板语句,实现所需的功能并进行代码测试、兼容性测试和代码改进。
  • 如果需要公开您的插件,可以用插件导出的方式,将插件配置信息导出到一个文本文件中,连同相应的程序和模板文件一同打包。同时,编写一个适合新手的插件的说明书也是必不可少的,其中包括:插件适用的 Discuz! 版本、功能概述、兼容性声明、安装方法、使用方法、卸载方法等等。
  • 将插件提供给他人,或自己使用,根据使用者反馈,对插件进行完善。插件实现流程至此结束。

文件命名规范

Discuz! 按照如下的规范对程序和模板进行命名,请在设计插件时尽量遵循此命名规范:

  • 可以直接通过浏览器访问的普通程序文件,以 .php 后缀命名。
  • 被普通程序文件引用的程序文件,以 .inc.php 后缀命名。
  • 被普通程序文件,或引用程序文件引用的函数库或类库,以 .func.php(函数库) 或 .class.php(类库) 后缀命名。
  • 模板文件,以 .htm 后缀命名,模板文件只存在于 ./templates 目录中。
  • 模板语言包文件,以 .lang.php 后缀命名,语言包文件只存放于 ./templates 目录中,与模板文件同级目录。
  • 被编译后的模板文件,以 .tpl.php 后缀命名,前面的数字是模板套系的 ID,下划线后面的是模板原名,编译模板文件只存在于 ./forumdata/templates 目录中。
  • 动态缓存文件,存放于 ./forumdata/cache 目录中,依据不同的功用进行独立的命名。
  • 使用后台数据备份功能生成的备份文件,通常以 .sql 为后缀,存放于 ./forumdata/ 目录中。
  • 有些目录中存在内容为空白的 index.htm 文件,此类文件是为了避免 Web 服务器打开 Directory Index 时可能产生的安全问题。

common.inc.php 模块功能白皮书

./include/common.inc.php 是 Discuz! 的通用初始化模块程序,其几乎被所有的外部代码所引用,在您开始插件设计之前,可以先对该模块的大致功能做一定的了解。common.inc.php 主要完成了以下任务:

  • 对不同 PHP 及操作系统环境做了判断和兼容性处理,使得 Discuz! 可以运行于各种不同配置的服务器环境下。
  • 初始化常量 IN_DISCUZ 为 TRUE,用于 include 或 require 后续程序的判断,避免其他程序被非法引用。
  • 读取论坛所在绝对路径,存放于常量 DISCUZ_ROOT 中。
  • 加载所需的基本函数库 include/global.func.php。
  • 通过 config.inc.php 中提供的数据库账号信息,建立数据库连接。Discuz!支持数据表的前缀,如需获得表的全名,可使用”{$tablepre}tablename” 或 $tablepre.’tablename’的方式。
  • 判断用户是否登录,如登录标记 $discuz_uid 为非 0,同时将 $discuz_user(加了 slash 的用户名,可用于不加修改的插入数据库)、 $discuz_userss(原始的用户名,可用于页面显示)、$discuz_pw(用户密码的MD5串)、$discuz_secques(登录提示问题的加密串)等相应用户信息赋值。
  • 判断用户管理权限,将管理权限标记 $adminid 为 -1~3 中间的值。-1 代表为特殊用户组用户。0 代表普通用户;1 代表论坛管理员;2 代表超级版主;3 代表论坛版主。将用户权限按照其所在的主用户组 ID 标记为 $groupid,相关权限从该 $groupid 所对应的系统缓存中读出(./forumdata/cache/usergroup_$groupid.php)。将用户扩展权限按照其扩展用户组 ID 标记为 $extgroupids,中间以 \t(tab) 分隔,格式为“$groupid1\t$groupid2...”,扩展用户组用于确定用户的扩展浏览权限,例如能否访问某些有特殊权限设定的论坛等。
  • 读入系统设置中的各种变量,并根据 Cache 模块的设定,根据当前被调用的程序文件名(如 index.php,forumdisplay.php 等等)读入相应的缓存代码。缓存代码被存放于 ./forumdata/cache/ 中。除了对应当前程序的缓存,可能还会加载一些通用的缓存数据,例如整个论坛的设置(./forumdata/cache/cache_settings.php)、界面风格(./forumdata/cache/style_x.php)、当前用户的用户组(./forumdata/cache/usergroup_x.php)、管理组权限(./forumdata/cache/adminusergroup_x.php)等。
  • 缓存数据的格式,大多是存放在 $_DCACHE['cachename'] 数组中,有些常用的参数,如系统设置中的参数、风格界面等,通常还被进行了展开操作(extract)或使用常量进行赋值。
  • 用户如果处在登录状态,会自动读出 members 表相关用户的参数值,用户的个性设置参数:如时差、时间格式、界面风格等等,会根据实际情况覆盖系统默认值,因此在后续程序通常不用再做判断。
  • 如果程序提交的 URL 中包含 tid=x 或 fid=x,common.inc.php 模块会自动读出其所对应的论坛记录及包括 access masks、版主设定等相应权限,记录在 $forum 变量中。后续程序只要通过URL将tid或fid传递过来,便可通过 $forum 数组的存在性或相关参数来对论坛权限进行判断,不需要再读 forums 表的资料。

插件接口概述

使用管理员账号登录 Discuz! 系统设置,在左侧菜单将可以看到“插件设置”和“插件管理”两个选项,使用超级版主或版主账号登录,将只出现“插件设置”一个选项。“插件管理”是控制插件打开与否、设计插件模块、菜单、参数和使用权限的地方,插件开发者可以依照设计意图,在此进行插件的初步设置,这里同时也提供插件导入和插件开关的功能,用于导入他人设计的插件和对插件的可用状态进行变更。“插件设置”是对已经安装的插件进行设置的地方,供使用者对插件参数进行调整以实现不同的插件功能。即前者主要面向开发者,后者主要面向使用者。


开始编写一个新插件,请首先在插件管理中,输入新插件的名称和惟一标识符。名称用于表明此插件的用途,例如设置为“虚拟银行插件”。惟一标识符用于在后续的插件模块中调用本插件,不可与现有插件重复,命名规则限制与 PHP 变量命名相同,虽然初次设置后仍可改动,但强烈建议一次性将此配置设置好,否则可能涉及到很多代码方面的变更,增加编码的麻烦。请注意:惟一标识符请不要设置的过短,或使用有可能与其他插件重复的命名,例如制作此插件的公司叫做 Comsenz Inc.,插件名称是“虚拟银行插件”,惟一标识符可设置为“comsenz_virtual_bank”,后面将以“虚拟银行插件”和 “comsenz_virtual_bank”为例进行说明。


在插件管理中添加插件后,仅仅是增加了一条插件记录,后面还需要很多相关的设计和设置。在列表中选择插件的“详情”进入插件的详细设置。插件设置分为三个部分:

  • 插件基本设置:
  • 设置插件的基本参数,配置项目右边括号中的内容,为此设置对应的参数名称,调用方法将在后面的《参数读取与缓存控制》中详细说明。

  • 插件模块和自定义菜单:
  • 插件接口默认提供四种可选的模块方式:

    • 直接链接(前台菜单):可在前台右上角加入一个菜单项,可自主指派菜单链接的 URL。注意:由于引用外部程序,因此即便设置了模块的使用等级,您的程序如需权限判断,仍需要引用 common.inc.php 和插件相关的缓存文件(将在后面的《参数读取与缓存控制》中详细说明),并自行判断使用等级是否合法。
    • 前台调用(前台菜单):与直接链接类似,但其调用的是插件的一个模块,模块文件名指派为“./plugins/插件目录/插件模块名.inc.php”,由 plugin.php 调用此模块,调用 URL 将在后面的《编写插件的原则与注意事项》中详细说明。
    • 后台调用(后台菜单):可在后台插件设置中为此插件增添一个管理模块,模块文件名指派为“./plugins/插件目录/插件模块名.inc.php”,由 admincp.php 调用此模块,调用 URL 将在后面的《编写插件的原则与注意事项》中详细说明。
    • 包含运行(无菜单):可设置一个在论坛所有页面均包含运行的脚本,此脚本在 ./include/common.inc.php 中加载,脚本文件名指派为“./plugins/插件目录/插件模块名.inc.php”。请注意,为了不导致错误的插件影响论坛运行,在 common.inc.php 加载此模块时,屏蔽了错误信息,因此请务必仔细检查是否存在语法错误,任何微小的语法错误都将不被提示出来,并且导致此模块不被正常加载。如果您配置了不正确的包含脚本而导致论坛系统设置无法使用,删除服务器上相应的脚本文件即可解决。

    您可以为每个模块设置不同的使用等级,例如设置为“超级版主”,则超级版主及更高的管理者(例如论坛管理员)可以使用此模块。

  • 插件钩子设置:
  • 插件钩子能够将插件代码埋藏在程序中的任意位置,从而实现更加灵活的插件功能,最大限度的减少对原有程序代码的修改。 论坛版本升级后,只需将相应钩子重新埋入相应程序中,原有插件即可继续使用。 关于插件钩子的具体设计方法请见下面的《插件钩子的设计》。

  • 插件变量配置:

插件接口中提供了一个通用的插件配置管理程序,在大多数情况下可实现插件的参数配置,省却了插件开发者自行编写后台管理模块(即上面提到的“后台调用(后台菜单)”模块)的麻烦。通常情况下,应优先使用通用插件配置管理程序来实现插件的参数配置,只有在通用程序确实无法实现时,才自行编写后台管理模块。输入配置名称和配置变量名、选择合适的配置类型后,即可为此插件增加一个配置变量,点“详情”可以编辑此配置变量的更多信息。为了方便插件程序调用使用者配置好的参数,配置变量同样被存放在了缓存文件中,读取方法将在后面的《参数读取与缓存控制》中详细说明。

注意:您只有在插件管理中将插件设置为“可用”,以上设置才能生效。

参数读取与缓存控制

编写插件程序时,可能需要读取一些插件的信息,如果插件需要使用者进行配置,还需要读取使用者设置的参数值。Discuz! 允许插件程序使用数据库读取和缓存读取这两种方法获取插件信息和参数。Discuz! 的插件接口已经对插件信息进行了合理的缓存,使用缓存读取的方式,将比数据库读取速度更快,消耗的资源更是几乎可以忽略不计。缓存读取唯一的局限是需要插件使用插件接口提供的通用后台管理程序。如果使用自定义后台模块的方式,需要后台模块将参数存放到 pluginvars 数据表中,才能被系统正常缓存。我们强烈推荐您通过缓存读取插件信息和配置数据。

插件数据结构

插件数据使用两个数据表存放,分别是 plugins 和 pluginvars。前者用于存放插件信息:安装了多少个插件,就有多少条记录;后者用于存放插件的配置参数和配置值:所有已安装的插件总共有多少个配置项目,就有多少条记录。下面的表格列出了这两个表的主要字段及其用途说明。

plugins 表:

pluginid插件的惟一 ID,自动递增
available插件是否可用,1=是,0=否
adminid 使用系统设置中插件接口自带的插件参数设置程序所需的最低权限等级要求,1=管理员,2=超级版主,3=版主
name插件名称
identifier插件惟一标识符
description插件简介
datatables插件数据表,不包含前缀,多个表使用半角逗号“,”分隔
directory插件所在目录,例如设置为 comsenz_bank,则对应论坛目录的位置为 ./plugins/comsenz_bank/
copyright插件版权信息
modules 插件模块信息,数组格式,使用 serialize() 序列化后存放

pluginvars 表:

pluginvarid插件配置的惟一 ID,自动地增
pluginid本项配置所隶属的插件 ID
displayorder本项配置的显示顺序,数值低的排在前面
title插件配置的名称
description插件配置的简介
variable插件配置的变量名
type插件配置的类型
value插件配置的值
extra当本项配置为“选择(select)”时,可选的取值范围

如果您使用自行编写的插件后台管理模块进行插件参数配置,请尽量将配置项目按照 pluginid 的对应关系,将参数存储于 pluginvars 表中,这样系统就可以自动将您增加的配置参数缓存起来,以供插件程序进行调用。

插件参数读取

了解了 Discuz! 插件存储的数据结构后,您可以在插件程序中根据需要选择合适的数据读取方式。由于数据库读取方式可以由数据结构推断而来,因此这里只介绍缓存读取的方式,这种方式是我们强烈推荐的插件数据读取方式。

在管理者配置好插件信息,或用户进行插件的参数设置之后,系统将根据插件设置的惟一标识符,自动生成一个插件数据的缓存文件,例如惟一标识符为 comsenz_virtual_bank,则缓存文件位于 ./forumdata/cache/plugin_comsenz_virtual_bank.php,您可以打开此文件查看其中的数据内容和格式。缓存采用数组的方式进行存储,引用此文件即可将所需的插件参数一次性赋值。

其中,$_DPLUGIN['comsenz_virtual_bank'] 这个数组下标,为插件的惟一标识符,所有插件缓存数据,一经被引用,就会赋值到 $_DPLUGIN 这个多维数组中。modules 描述了这个插件的模块信息,其中 type 为 1~4 的整数值,从小到大依次为“直接链接(前台菜单)”、“前台调用(前台菜单)”、“后台调用(后台菜单)”、“包含运行(无菜单)”;vars 描述了这个插件的配置变量,前面为变量名,后面为使用者赋予这个变量的值。

编写插件的原则与注意事项

请在您动手编写插件之前,还需要仔细的阅读以下原则,遵循这些原则,将有效的避免可能发生的问题:

  • 所有与插件的程序,包括其全部的前后台程序,请全部放入 ./plugins 目录中,同时在插件的安装说明中指出,插件的文件需要复制到哪些目录。为了避免与其他插件冲突,请尽量建立 ./plugins 下的子目录,并将插件程序放置于子目录下,这样您编写的插件将获得更好的兼容性。
  • 如果您的插件包含“前台调用(前台菜单)”模块,该模块将统一用 plugin.php?identifier=xxx&module=yyy 的方式调用,请在相应链接、表单中使用此方式。其中 xxx 为插件的惟一标识符,yyy 为模块名称。前台插件外壳程序 plugin.php 已经加载了通用初始化模块(./include/common.inc.php),不需再次引用。
  • 如果您的插件包含“后台调用(后台菜单)”模块,该模块将统一用 admincp.php?action=plugins&identifier=xxx&mod=yyy 的方式调用,请在相应链接、表单中使用此方式。其中 xxx 和 yyy 的定义与“前台调用(前台菜单)”模块中的相同。系统还允许用 admincp.php?action=plugins&edit=$edit&mod=$mod 的方式来生成链接和表单地址,$edit 和 $mod 变量已经被插件后台管理接口赋值,因此将这两个变量值带入 URL 中也是被支持的。由于后台模块是被 admincp.php 调用,因此已加载了通用初始化模块(./include/common.inc.php)并进行了后台管理人员权限验证,因此模块程序中可直接写功能代码,不需再进行验证。
  • 请勿绕过插件的前后台外壳(plugin.php 和 admincp.php)而以直接调用某程序的方式编写插件,因为这样既导致了用户使用不便,代码冗余和不规范,同时又产生了因验证程序考虑不周到而带来的安全隐患。您可以在任何地方,包括链接、表单等处方便的使用上述 URL 地址对插件模块进行调用。
  • 所有与插件有关的程序,包括全部的前后台程序,因全部使用外壳调用,请务必在第一行加入

以免其被 URL 直接请求调用,产生安全问题。

  • 一般情况下,您发布插件请使用插件导出的功能,以方便使用者一次性导入插件的配置数据,极特殊的情况下,也可以分步骤告知使用者如何进行插件配置管理和安装此插件。
  • 如果功能独立,请尽量使用单独程序的方式编写插件(即外挂型插件),而尽量少的对论坛本身代码进行修改,这将为使用者今后的升级带来很大方便。
  • 您可以修改 Discuz! 本身的数据结构,但更推荐在不很影响效率的前提下将插件数据用另外的数据表存储,因为不能排除您增加的字段或索引和今后版本 Discuz! 核心数据字段重名的可能。在任何情况下,请不要删除 Discuz! 标准版本数据结构中已有的字段或索引。
  • 请在插件说明书中对插件做以详尽的描述,例如增加了哪些字段、哪些表,修改了或新增了哪些程序,版本兼容性,后续支持的提供方式(例如不提供支持,或以什么样的方式提供)。如果方便,请尽可能提供插件的卸载方法,例如去除哪些字段、删除哪些新增的程序、将哪些被插件修改的程序恢复原状等等,使用者会感激您为此付出的辛勤劳动,甚至愿意支付相应的费用支持您未来的发展。
  • 如果插件使用另外的数据表存储,请在插件管理中准确的设置插件所使用的数据表名称(不包含前缀),这样用户在备份数据的时候,能够把插件数据一同备份。
  • Discuz! 自 4.0.0 版本起,内置了 8 种自定义积分,存储于 members 表中的 extcredits1 至 extcredits8 字段中,类型为有符号整数,您可以在引用 common.inc.php 后,在 $extcredits 或 $_DCACHE['settings']['extcredits'] 中读取 8 种积分的启用信息(详情请参考 ./forumdata/cache/cache_settings.php)。插件程序中如需更新用户积分,可直接 UPDATE 相应的积分字段,无需其他操作。

插件钩子的设计

插件钩子的设计,需要您具有一定编程基础,比较了解 Discuz! 论坛程序的结构,并能够使用 PHP 语言撰写代码。对于普通用户,可以略过以下内容。插件钩子(以下简称“钩子”)属于插件的一部分,因此在设计钩子之前应当首先进入后台——插件管理,新增插件或者编辑一个现有的插件,即可看到相关设置。

钩子的添加

  • 钩子名称:在一个插件内,钩子的名称是唯一的,不可重复。名称可以由英文字母、数字和“_”组成,不支持中文,最长255个字符。为了便于理解和记忆钩子的作用, 名称应当尽量简洁清晰,能够表述一定的含义。注意:钩子名称对字母大小敏感,例如:Index_start 和 index_start 将视为两个不同的钩子。
  • 钩子描述:对钩子的详细说明,如功能介绍、调用方法、使用方法等。
  • PHP代码:这里是钩子的核心内容,也是一段PHP代码,需要您自行设计,完成钩子需要处理的数据或者需要执行的操作。
  • 可用:每个插件允许有多个钩子,您可以自由选择关闭或者开启某个钩子。

钩子的删除

在钩子管理界面,您可以随时删除某一个钩子。 钩子删除以后,您应当及时修正放置钩子的程序文件,清除钩子标记,以免影响您论坛的正常使用。

钩子的编辑与升级

  • 编辑:插件设计阶段,您可能需要随时编辑钩子,每次更改,系统会自动更新缓存文件,您可以立即看到更改的效果。如果是更改钩子名称,那么您可能需要调整钩子放置的程序,修改钩子调用的名称。
  • 升级:论坛程序进行升级之前,您应当使用插件的导出功能,导出插件备份。论坛升级并正常运行后,再导入插件备份,修改相关程序,重新安放钩子。

钩子的放置与调用

钩子设计完成以后,您需要在相应的程序中安放钩子,不同钩子由于作用的不同,放置的位置也是不同的。 安放钩子,您仅仅需要将钩子的调用代码放入即可。调用代码格式如下:


例如:调用 插件demo 的钩子 testhook, 我们需要在程序中适当的地方加入下面的代码

设计范例

此处我们为您提供一个使用钩子技术的插件范例,完成功能十分简单,旨在使您直观的了解钩子的使用。此范例实现了当游客访问论坛首页时,强制用户登录的功能。

  • 进入系统设置中的插件管理,添加一个名称和惟一标识符均为 demo 的插件。
  • 编辑插件 demo 详情,找到“插件钩子设置”,添加一个名为 index_force_loggedin 的钩子,然后提交。
  • 编辑钩子 index_force_loggedin,按如下内容填写设置:
    • 钩子描述:当游客访问论坛首页的时候,程序会弹出提示框,并自动跳转到登陆页面。
    • PHP代码:
  • 提交后,回到此插件的设置页面。将钩子 index_force_loggedin 设置为可用。
  • 点击左侧导航,进入插件管理,将插件 demo 设置为可用。
  • 编辑论坛程序 index.php 安放钩子,方法如下:
    • 查找代码:
    • 在上述代码下放添加代码:
    • 保存文件后将文件上传到服务器。
    • 至此,一个简单的使用钩子实现的插件已经彻底完成。您可以退出登陆并访问论坛首页,测试一下插件的效果。

    Discuz! 插件的钩子技术,为广大的插件开发者提供了一个更加灵活的插件设计机制。当 Discuz! 升级后,用户只需重新将钩子调用代码安放到程序中原来的位置,就几乎可以继续使用原来已安装的插件,降低了对于程序修改的幅度和插件安装的难度,更加有利于插件程序的规范、管理、维护、相互交流。因此我们强烈建议插件开发者能够深入研究个应用这一机制,创作出越来越多的优秀插件。

    意见反馈

    插件接口是 Discuz! 开发组为了方便插件设计、安装和使用而专门开发,虽然经过长期的优化和改进,可能仍然会有不够合理或不够完善的地方,欢迎各位插件程序员在使用此接口的过程中,为我们提出意见和建议,感谢您的支持。

真正的尊敬,既不属于那些批评别人头头是道的人,也不是属于给强人指出过错、指点别人哪里做的不好的人。真正的尊敬,是属于那些勇于亲身投入战场,脸上沾满了尘土、汗水和鲜血的奋斗者们。他们坚持不懈的努力,尽管曾经犯下错误,并一再失败,但他们满怀激情,执著不懈,将生命奉献于崇高的事业。他们为经过艰辛努力最终取得的伟大成就而自豪,如果失败,他们也败得荣耀。因此,那些既没赢得过胜利,也没懂得什么叫做失败的,冷漠、胆怯的灵魂,是永远也无法与这些真正值得尊敬的人相提并论的。
http://www.cnedwin.com

TOP

Discuz! 插件设置及管理

插件,是基于 Discuz! 论坛系统之上,设计开发的一种小程序或小方案,用来实现对论坛现有功能扩展和改进。由于 Discuz!已具有相当完备的底层架构,因此插件并不需要具备很多深层的设计思想,也不需要很专业的开发人员,只要把想实现的功能与论坛的基本体系挂接起来,论坛就能拥有更加个性化的功能。
那么我针对插件管理和设置做一个详细的说明。插件管理主要是针对插件设计者使用,而一般的使用者,使用插件设置即可。
我们进到后台 -> 扩展设置 -> 论坛插件,可以看到个当前安装的插件。如图 1 所示:
对于插件设计者来说,插件管理到底是怎么使用的呢?或者怎么设计一个插件呢?进插件管理选项。首先得新增加一个插件的配置,那么在新增那里,填写好插件名称和唯一标识符,提交后,就可以得到一个新的插件配置了的。如图 2 所示:
下面的那个导入插件数据,这个文本输入框,这个是把插件作者设计好的配置,直接粘贴,即可导入论坛。如果插件在论坛的版本不一致的情况下开发的,那么勾选上 允许导入不同版本 Discuz! 的插件(易产生错误!!) 即可导入插件的配置详细。
在我们新增加了一个插件配置后,我们得对插件的配置进行细节的配置。
那么我们增加好的列表里面,选择对应的插件,点详情,如图 3 所示:
这个就是点帐户中心的详情,进来看到的各个基本配置。但是有这个基本配置还是不够的。
那么需要增加对应的模块来实现需要的功能。但是因为为了插件的安全和使用我们提供的统一调用接口,那么配置对应的模块:如图 4 所示:
增加对应模块的方法,同样是写上模块的名称(模块的标识符)和 菜单名称即可增加新的模块。
直接链接URL,这个选项,如果填写,那么这个就是在前台增加一个url链接,直接跳转到你填写的地址。
模块类型有下面几种:直接链接(前台菜单):可在前台右上角加入一个菜单项,可自主指派菜单链接的 URL。注意:由于引用外部程序,因此即便设置了模块的使用等级,您的程序如需权限判断,仍需要引用 common.inc.php 和插件相关的缓存文件,并自行判断使用等级是否合法。
前台调用(前台菜单):与直接链接类似,但其调用的是插件的一个模块,模块文件名指派为“./plugins/插件目录/插件模块名.inc.php”,由 plugin.php 调用此模块。
后台调用(后台菜单):可在后台插件设置中为此插件增添一个管理模块,模块文件名指派为“./plugins/插件目录/插件模块名.inc.php”,由 admincp.php 调用此模块。
包含运行(无菜单):可设置一个在论坛所有页面均包含运行的脚本,此脚本在./include/common.inc.php中加载,脚本文件名指派为“./plugins/插件目录/插件模块名.inc.php”。请注意,为了不导致错误的插件影响论坛运行,在common.inc.php加载此模块时,屏蔽了错误信息,因此请务必仔细检查是否存在语法错误,任何微小的语法错误都将不被提示出来,并且导致此模块不被正常加载。如果您配置了不正确的包含脚本而导致论坛系统设置无法使用,删除服务器上相应的脚本文件即可解决。
您可以为每个模块设置不同的使用等级,例如设置为“超级版主”,则超级版主及更高的管理者(例如论坛管理员)可以使用此模块。前后台调用方式为:
如果您的插件包含“前台调用(前台菜单)”模块,该模块将统一用plugin.php?identifier=xxx&module=yyy 的方式调用,请在相应链接、表单中使用此方式。其中 xxx为插件的惟一标识符,yyy 为模块名称。前台插件外壳程序 plugin.php已经加载了通用初始化模块(./include/common.inc.php),不需再次引用。
如果您的插件包含“后台调用(后台菜单)”模块,该模块将统一用admincp.php?action=plugins&identifier=xxx&mod=yyy的方式调用,请在相应链接、表单中使用此方式。其中 xxx 和 yyy 的定义与“前台调用(前台菜单)”模块中的相同。系统还允许用admincp.php?action=plugins&edit=$edit&mod=$mod的方式来生成链接和表单地址,$edit 和 $mod 变量已经被插件后台管理接口赋值,因此将这两个变量值带入 URL中也是被支持的。由于后台模块是被 admincp.php调用,因此已加载了通用初始化模块(./include/common.inc.php)并进行了后台管理人员权限验证,因此模块程序中可直接写功能代码,不需再进行验证。
这些是模块的设计,基本的变量设置,例如本插件需要用到的设置变量,那么该怎么增加的呢?
在前面点进某个插件的详情,在最下面,就是显示的是本插件当前所有的变量设置:如图 5 所示:
变量的增加和前面插件的增加类似。例如增加好了一个 管理员是否可用的 这个变量设置,点详情,如图 6 所示:
根据每一项的左边的提示就可以完成一个变量的设置。
我们设计的插件变量已经设置好了之后,如果我们需要修改到 Discuz! 本身的文件,那么我们可以使用插件钩子。如图 7 所示:
点详情:如图 8 所示:
最后调用是在需要修改代码的页面增嵌入例如 eval($hooks['accounts_hook']); 这样的代码即可。
现在整个插件的管理我介绍的差不多了。
那么设计出来的插件效果是什么样的呢,那么我们可以到插件设置来看,进入插件设置,如图 9 所示:
这里就把论坛安装的所有的插件都罗列出来。
就以我们增加的插件帐户中心来看看我们的设计:
首先是插件参数设置:如图 10 所示:
对应插件管理的设置:如图 11 所示:
参数设置的效果就是这个样子表现了的。
那么 模块:绑定搜索 的效果,如图 12 所示:(访问的地址:admincp.php?action=plugins&identifier=accounts&mod=stats)
这个对应的插件管理,如图 13 所示:
那么实际上是后台调用执行了我自己写的模块代码:./plugins/accounts/stats.inc.php ,如图 14 所示:
模块:参数设置 的效果,如图 15 所示:(访问地址:admincp.php?action=plugins&identifier=accounts&mod=setting)
对应插件管理:如图 16 所示:
那么实际上是后台调用执行了我自己写的模块代码:./plugins/accounts/setting.inc.php 。
后台的插件设置已经已经介绍完毕,那么刚才还有一个 帐户中心的这个模块,这个到哪去了呢?
这个设置为前台的链接:如图 17 所示:
可以看出是前台的菜单模块,而且是直接链接的。
那么到前台看是什么效果的呢?如图 18 所示:
就是显示一个链接,跳到你设置的直接链接的 url 。
一个插件配置设计基本就是上面说明了的,我们可以根据需要关闭或者导出这个插件配置如图 19 所示:
看完上面所有的说明,是不是发现设计一个插件也是如此简单!
真正的尊敬,既不属于那些批评别人头头是道的人,也不是属于给强人指出过错、指点别人哪里做的不好的人。真正的尊敬,是属于那些勇于亲身投入战场,脸上沾满了尘土、汗水和鲜血的奋斗者们。他们坚持不懈的努力,尽管曾经犯下错误,并一再失败,但他们满怀激情,执著不懈,将生命奉献于崇高的事业。他们为经过艰辛努力最终取得的伟大成就而自豪,如果失败,他们也败得荣耀。因此,那些既没赢得过胜利,也没懂得什么叫做失败的,冷漠、胆怯的灵魂,是永远也无法与这些真正值得尊敬的人相提并论的。
http://www.cnedwin.com

TOP

Discuz! 插件的钩子的使用技巧

这里介绍如何更方便和容易的使用钩子

1、如果我们钩子里面的代码比较多,我建议独立一个文件写代码,再 include 这个独立的文件

钩子的代码就是

或者是(根据你自己的需要)

自己要实现的功能的代码就写在 ./plugins/pluginname/mode.inc.php文件里面实现。

这个对于测试和插件的升级都比较有好处的。

例如当发布了一个插件,为了安装的时候修改代码尽量的简洁(我们推荐你这样做),你使用到了钩子,但是因为发布不久,你需要更新钩子,所以得教会用户在不删除配置的情况下更新钩子的配置。那就相对比较麻烦,如果像我上面的设置的话,那么只需要更新文件即可,就是叫用户上传覆盖文件即可,非常方便。

2、模板中使用钩子

我们知道在Discuz!的模板语法中有 {eval parm},执行php代码的标记。那么要在模板上使用钩子,只要 {eval eval($hooks['demo_testhook']); }

那样,那么就完全可以执行钩子里面的代码了。

钩子是一个非常灵活的机制,所以大家可以仔细的研究下这个机制,那么设计出来的插件的安装难度可以大大的降低哈。

真正的尊敬,既不属于那些批评别人头头是道的人,也不是属于给强人指出过错、指点别人哪里做的不好的人。真正的尊敬,是属于那些勇于亲身投入战场,脸上沾满了尘土、汗水和鲜血的奋斗者们。他们坚持不懈的努力,尽管曾经犯下错误,并一再失败,但他们满怀激情,执著不懈,将生命奉献于崇高的事业。他们为经过艰辛努力最终取得的伟大成就而自豪,如果失败,他们也败得荣耀。因此,那些既没赢得过胜利,也没懂得什么叫做失败的,冷漠、胆怯的灵魂,是永远也无法与这些真正值得尊敬的人相提并论的。
http://www.cnedwin.com

TOP

Discuz! 插件代码的安全规范

总的来说 PHP 还是相对安全的 Web 程序,但是由于一些代码在处理方式上的不成熟导致了安全隐患.由于这个议题范围太广,所以推荐 PHPCHINA 的 Essential PHP Security -PHP安全基础 一书给大家,希望对大家有帮助。更详细的 PHP 安全信息可以登录 php.net 查找。

那么,对于插件安全究竟我们要做些什么怎么做?
1、变量的初始化

这里不讨论 magic_quotes_gpc 和 register_globals 的设置情况,大家只要注意不要“无中生有”变量,每个变量的得到都是自己初始化过的。
2、逻辑关系清楚

对于逻辑的判定不是一句话能够说明白的,举个简单的例子,在判断上传文件的时候,我们判断的依据是他的后缀是否在我们允许的后缀里面,如果是允许的就执行上传,反之就提示上传文件后缀不对,但是如果用户上传的文件名是 webshell.xxx.mht(允许mht 文件上传,mht 是一种网页存储格式),于是文件上传了,在 apache 系统的默认配置下,这个文件是会用 PHP 来解析的,利用这个算是 BUG 的问题吧,小版本人就曾伙同PHP安全界知名人士(帮他匿了)对我们学校的服务器完成了入侵,并最终取得了 root 权限(目前俺们学校的服务器已经修正此问题),举这个例子是为了说明程序处理的重要性,如果当时多一步判断上传的文件,也许这个安全问题就不再存在,其实这个例子来说明逻辑关系并不是很合适,但是程序处理真的是一个非常重要的部分。
3、' '与" "的区别运用

单引号中,任何变量($var)、特殊转义字符(如“\t \r \n”等)不会被解析,因此PHP的解析速度更快,转义字符仅仅支持“\’”和“\\”这样对单引号和反斜杠本身的转义;

双引号中,变量($var)值会代入字符串中,特殊转义字符也会被解析成特定的单个字符,还有一些专门针对上述两项特性的特殊功能性转义,例如“\$”和“{$array[‘key’]}.这样虽然程序编写更加方便,但同时PHP的解析也很慢;

数组中,如果下标不是整型,而是字符串类型,请务必用单引号将下标括起,正确的写法为 $array[‘key’],而不是 $array[key],因为不正确的写法会使PHP解析器认为key是一个常量,进而先判断常量是否存在,不存在时才以“key”作为下标带入表达式中,同时出发错误事件,产生一条 Notice 级错误。

因此,在绝大多数可以使用单引号的场合,禁止使用双引号.依据上述分析,可以或必须使用单引号的情况包括但不限于下述:

字符串为固定值,不包含“\t”等特殊转义字符;

数组的固定下标,例如$array[‘key’];

表达式中不需要带入变量,例如$string = ‘test’;而非$string = “test$var”;
4、数据的过滤与处理

对于任何得到的数据在不能确定或者不能充分确定其来路的时候一定要进行过滤与处理,在数据进入程序运行处理阶段之前,一定要保证它的准确性和正确性。
5、不要相信任何数据的准确性和正确性

这条视乎是和上面一条雷同,但是即使是从数据库中查出来的数据也一样不能确定,比如生成 cache 文件,如果用户 POST 的数据错误不是我们期望的数据,而“恰巧”生成到文件中,于是一个webshell产生了,同样这个例子也不是很合适,我只是希望大家明白这么一点,如果我们没有一个很好的处理数据的方式,那么代码的安全崩溃也就指日可待。
6、不要妄图直接把低版本的 Discuz! 插件直接运行

由于每个大版本的升级都会带来系统构架的一些变化,可能旧版本的插件仍然可以使用,但是或许一些不可预料的问题正在隐藏中,所以建议任何低版本的 Discuz! 插件最好是经过仔细研究之后再公告说可以适用新版本 Discuz! 插件。
真正的尊敬,既不属于那些批评别人头头是道的人,也不是属于给强人指出过错、指点别人哪里做的不好的人。真正的尊敬,是属于那些勇于亲身投入战场,脸上沾满了尘土、汗水和鲜血的奋斗者们。他们坚持不懈的努力,尽管曾经犯下错误,并一再失败,但他们满怀激情,执著不懈,将生命奉献于崇高的事业。他们为经过艰辛努力最终取得的伟大成就而自豪,如果失败,他们也败得荣耀。因此,那些既没赢得过胜利,也没懂得什么叫做失败的,冷漠、胆怯的灵魂,是永远也无法与这些真正值得尊敬的人相提并论的。
http://www.cnedwin.com

TOP

Discuz! Passport 接口技术文档

从 Discuz! 4.0.0 RC4 版本开始,Discuz! 内嵌了一个独特的 Passport(通行证) 接口,利用此接口,用户将很容易将论坛与其他应用程序整合,而实现统一登录与退出、用户数据共享、积分同步等功能。可以整合的应用程序包括内容管理系统(CMS)、商城系统、游戏系统等等,如您对这方面功能有兴趣或有需求,请继续阅读本文档。

Discuz! Passport 的优点

Discuz! Passport 系统使用了 Discuz! 独有的技术,并不等同于以往使用过的一些方法,与传统的实现方式相比,具备(不限于)以下优势:

  • 基于私有密匙的低相关性可逆加密算法,配合 MD5 校检码技术,使得暴力破解或伪造几乎不可能。
  • 应用程序可与论坛放置于不同的服务器及不同的域名下。可基于不同操作系统、不同程序语言和不同数据库平台,具备真正的平台无关性。
  • 不需要任何形式的数据库连接、或强制把两套应用程序的数据放在同一数据库甚至同一数据表中。论坛与应用程序都有各自的用户数据表,只是在需要时进行无缝同步操作。
  • 对应用程序的代码改动简便易行,可最快速的完成应用程序与论坛间的整合。

Discuz! Passport 的局限

您在开始利用 Discuz! Passport 进行二次开发时,需要了解这个系统的局限性,以对未来的工作进行正确的评估与安排。

  • 只能工作在用户密码不加密、可逆加密或 MD5 加密的情况下,否则论坛后台无法登录。
  • 只能与一种应用程序关联,即二方关联。不能实现三方关联或与更多的应用程序进行关联。
  • 应用程序需具有独立的注册、登录、退出页面和链接,否则需要自行修改论坛中的相应表单或程序。
  • 由于论坛的注册人数可能很多,例如百万级以上,且应用程序和论坛间的用户数据是同步的,因此要求应用程序能够稳定的负载大量用户的访问。

原理与流程

假设已设置如下变量或参数

  • 挂接 Discuz! Passport 的应用程序假设为一套 PHP 语言编写的 CMS 系统
  • Discuz! 的 URL 为 http://www.myforums.com
  • 应用程序的 URL 为 http://www.mywebsite.com
  • 应用程序的注册页面为 http://www.mywebsite.com/register.php
  • 应用程序的登录页面为 http://www.mywebsite.com/login.php?action=login
  • 应用程序的退出页面为 http://www.mywebsite.com/login.php?action=logout

开启通行证后的用户登录流程

  • 如果用户在论坛点击“登录”,则转向到事先设置好的应用程序登录页面(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。
  • 应用程序收到此请求后,按照惯例生成表单,并增加一个表单变量 ,将 GET 方式传递过来的 forward 参数通过表单进行传递。
  • 用户在应用程序的表单中填写登录信息,并提交到应用程序的登录验证程序。应用程序验证用户提交的用户名和密码的合法性:
    • 如果不通过:提示用户名密码错误,要求其返回上一页重新填写。
    • 如果通过,需要进行如下操作:
      • 设置自身 Cookie 或 Session,使得应用程序自身处于登录状态。
      • 检查表单中是否提交了 forward 变量,如有,则意味着登录请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward 变量,使得论坛登录后能够跳转回到应用程序中。
      • 通过 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 格式与结构将在后面进行说明。
  • Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
    • 根据 verify 判断 auth 和 forward 变量是否合法,如合法则继续,否则终止。
    • 将 auth 根据既定算法解密,并还原成数组,数组的内容与格式将在后面进行说明。根据数组中的内容,检查此用户是否存在。如存在,则根据上述数组中的内容 UPDATE 论坛中相应的用户资料。如不存在,则使用数组中的信息 INSERT 到论坛用户资料表中。
    • 论坛设置 Cookie 或 Session,使得论坛自身处于登录状态。
    • 根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。
  • 至此,登录流程结束

开启通行证后的用户退出流程

  • 如果用户在论坛点击“退出”,则转向到事先设置好的应用程序退出页面(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。
  • 应用程序收到此请求后,清除自身 Cookie 或 Session,使得应用程序自身处于非登录状态。
  • 检查是否提交了 forward 变量,如有,则意味着登录请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward 变量,使得论坛登录后能够跳转回到应用程序中。
  • 通过 header('Location: http://www.myforums.com/api/passport.php?action=logout&forward=http://yyy&verify=zzz') 的方式,将退出请求传递到论坛进行处理。其中 forward 用于告知论坛 Passport API 完成自身操作后转向到的 URL 地址,verify 用于验证 forward 变量的有效性。forward、verify 格式与结构将在后面进行说明。
  • Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
    • 根据 verify 判断 forward 变量是否合法,如合法则继续,否则终止。
    • 清楚论坛的 Cookie 或 Session,使得论坛自身处于非登录状态。
    • 根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。
  • 至此,退出流程结束。

开启通行证后的用户注册流程

  • 如果用户在论坛点击“注册”,则转向到事先设置好的应用程序注册页面(http://www.mywebsite.com/register.php),并在注册页面的 URL 中加入参数 forward(例如 http://www.mywebsite.com/register.php?forward=http://www.myforums.com/index.php),用于在注册后将用户导向到指定的 URL
  • 应用程序收到此请求后,按照惯例生成表单,并增加一个表单变量 ,将 GET 方式传递过来的 forward 参数通过表单进行传递
  • 用户在应用程序的表单中填写注册信息,并提交到应用程序的注册验证程序。应用程序验证用户提交信息的完整性和合法性:
    • 如果不通过:提示其问题所在,要求其返回上一页重新填写
    • 如果通过,需要进行如下操作:
      • 将用户资料插入到应用程序自身用户数据库中
      • 设置自身 Cookie 或 Session,使得应用程序自身处于登录状态
      • 检查表单中是否提交了 forward 变量,如有,则意味着注册请求可能是由论坛而来,将此变量传递到后面的请求中。如没有,自行生成 forward 变量,使得论坛注册后能够跳转回到应用程序中
      • 通过 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 格式与结构将在后面进行说明
  • Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后,进行如下操作:
    • 根据 verify 判断 auth 和 forward 变量是否合法,如合法则继续,否则终止
    • 将 auth 根据既定算法解密,并还原成数组,数组的内容与格式将在后面进行说明。根据数组中的内容,检查此用户是否存在。如存在,则根据上述数组中的内容 UPDATE 论坛中相应的用户资料。如不存在,则使用数组中的信息 INSERT 到论坛用户资料表中
    • 论坛设置 Cookie 或 Session,使得论坛自身处于登录状态
    • 根据应用程序反馈的 forward 值,通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL
  • 至此,注册流程结束

本部分中,加下划线显示的部分,是需要对您的应用程序进行更改的部分,事实上,这部分更改会非常容易和方便。

Discuz! Passport 参数规格与加密方式

私有密匙(passport_key)

由于一些关键参数采用了 GET 方式进行传递,即便两次 header 跳转并不会直接将链接显示在外面,但我们仍然对关键的参数进行了加密,私有密匙共有两个作用:其一是供下面提到的可逆加密算法(AzDGCrypt)进行数据的加解密。其二是生成不可逆验证字串(verify),以防止关键信息被伪造。


在启用 Discuz! Passort 后,您需要在应用程序和 Discuz! 后台配置两处私有密匙,这两处的内容必须完全相同,这样应用程序和论坛之间才能正常通信。私有密匙决定了加密算法的强度,因此密匙长度请不要小于 10 个字节,并包含字母、数字和符号,以保证系统的安全。

加密算法

Discuz! Passport 采用 Azerbaijan Development Group(AzDG)开发的可逆加密算法 AzDGCrypt 对用户资料进行加密。如提供正确的私有密匙,可通过本加密算法对数据进行加密及解密,因此只要保证私有密匙的保密性,即可确保数据传递过程中的安全。以下为 Discuz! Passport 中应用到的可逆加密算法,为了生成可以被 Discuz! Passport 正确解密的 auth 字串,需要将如下函数放置于应用程序中,并可在登录及注册时调用。

passport_encrypt()是加密函数,用法为 passport_encrypt($txt, $key),其中 $txt 是待加密的字串,$key 是私有密匙。

passport_decrypt()是解密函数,用法为 passport_decrypt($txt, $key),其中 $txt 是加密后的字串,$key 是私有密匙。

passport_encode()是将数组转换合成为字串形式存储的函数:变量名和数值之间用等号连接,如果数值包含特殊字符,使用 urlencode() 将其转码。多个变量间使用 & 分割。例如原始数组内容为 array('username' => 'abc', 'email' => 'my+discuz@gmail.com'),经过 passport_encode() 编码后结果为 username=abc&email=my%2Bdiscuz%40gmail.com。

信息字串(auth)

应用程序在收到登录或注册请求,并读取到用户资料后,请按如下的要求将用户资料及部分其他信息存放于一个数组之中。数组各键值的含义为:

  • cookietime
    应用程序保存该用户登录记录的时间,可为非负整数,单位秒,Discuz! Passport 收到此参数后,会设置同样的 Cookie 过期时间,这样应用程序和论坛可以保证同样的登录有效性。如不传递此参数,或参数数值不正确,则 Discuz! Passport 按照 0 设置 Cookie 有效期。
  • time
    应用程序所在服务器当前时间(9 或 10 位数字 Unix Timestamp),此参数用于 Discuz! 所在服务器当前时间进行比对,如果早于当前时间超过若干秒(取决于 Discuz! Passport 中的“验证字串有效期”设定),则视为本 auth 内容无效,避免此URL被人得知后可能的安全问题。
  • username
    用户登录或注册的用户名。Discuz! 的注册用户名规则为:
    • 长度 1~15 个字符,不得为空
    • 不得为 c:\con\con、游客(gb2312 或 BIG5 内码)、Guest
    • 不得包含 (,)、(*)、(")、([TAB])、([SPACE])、([\r])、([\n])、(<)、(>)、(&)其中之一

    如果应用程序提交过来的用户名不符合上述规则,Passport 将自动去处其中的特殊字符,将过滤后的结果写入数据库中。
  • password
    用户密码经 MD5 不可逆加密后的值。如果此密码使用非 MD5 加密,则应用程序和 Passport 不能正常关联和使用。
  • email
    用户 Email 地址(50 个字节以内)。
  • isadmin
    当前用户是否是应用程序的最高管理员,1=是,0=否。最高管理员的权限,将同步到论坛中去,其他下级管理员的身份将不进行同步,而由最高 管理员分别在不同的系统中进行设置。
  • credits
    当前用户在应用程序中的积分值,范围 -2147483648 到 2147483647,如果 Discuz! Passport 中设置了目标积分项,则用户登录时,Passport 会把应用程序传递过来的 credits 值同步到指定的论坛的指定积分项目中
  • gender
    当前用户的性别,1=男,2=女,0=未知。
  • bday
    当前用户的生日,格式 yyyy-mm-dd。
  • regip
    当前用户注册时的 IP 地址。
  • regdate
    当前用户注册的时间(9 或 10 位数字 Unix Timestamp)。
  • nickname
    当前用户的昵称(30 个字节以内,如传递此参数,必须打开相应用户组的昵称权限,否则用户在控制面板中提交个人资料时,会导致昵称失效)。
  • site
    当前用户的主页地址(包含http://)。
  • qq
    当前用户的 QQ 号码。
  • ICQ
    当前用户的 ICQ 账号。
  • msn
    当前用户的 MSN Messenger 账号。
  • yahoo
    当前用户的 Yahoo! Messanger 账号。

以上参数中,以黑体下划线显示的 time、username、password、email 是必须传递的参数,缺少上述参数 Passport 将无法正常工作。其他的参数是可选的,如果不传递某些参数,则 Passport 会进行识别,自动不更新没有传递的参数所在的字段。所有数值,请提供原始值,而非经过反斜线转义(addslashes)后的结果。

把上述信息存放于数组中,假定为如下的形式:

将其经过如下的加密变换,即可得到 auth 的值:

其中,passport_encode() 在前文已做了说明,用于将数组内容存放于特定的格式,$passport_key 是私有密匙。

切记:由于 $auth 中可能含有等号、加号等特殊字符,请将 $auth 经过 rawurlencode() 编码后再在 URL 中传递,否则可能会产生问题。

导向字串(forward)

导向字串用于通知 Discuz! Passport 在完成自身操作后,返回到哪一个 URL 地址,例如 http://www.myforums.com/forumdisplay.php?fid=2。如果 forward 为空,则默认导向到应用程序的首页

切记:由于 $forward 中可能含有冒号、问号、等号等特殊字符,请将 $forward 经过 rawurlencode() 编码后再在 URL 中传递,否则可能会产生问题。

验证字串(verify)

验证字串用户检验 auth 和 forward 两个参数的合法性,避免非法构造参数进行破坏的可能。无论 auth 和 forward 变量是否存在,验证字串(verify)的值均为:

其中,$action 是当前执行的 Passport 操作,如 login 等等;$auth 是用户信息加密后,并经 rawurlencode() 之前的内容。$forward 是经rawurlencode() 前的导向字串、$passport_key 是私有密匙。如果 verify 的值不匹配,则 Passport 拒绝进行下一步操作。

Discuz! Passport 设置与启用

内置关联

Discuz! 以战略合作的方式,与业内知名的产品实现了 Passport 关联,目前内置了 SiteEngine 建站引擎(http://www.siteengine.net)和 Shopex 通用型网上商店系统(http://www.shopex.cn)的相关接口,这样用户只须透过在两套软件中简单的设置,即可开启这些关联。

其他应用程序

由于 Discuz! Passport 的高可扩展性和平台无关性,使得您可以参照前文的说明,稍稍改动小部分的代码,便将任何 B/S 模式的应用程序与 Discuz! 进行关联。

参数设置

您可以在 Discuz! 系统设置中,看到相应的通行证设置功能,在 Discuz! 合作伙伴的软件中,也可以找到这些设置入口。相关的操作已比较简单,在此不再详细叙述。

特别说明

如果您先运营了论坛,后与其他应用程序启用了 Passport 关联,由于之前论坛中的用户数据没有同步,您需要先写一个导入程序,将论坛的用户数据导入到应用程序的用户表中,否则以往在论坛注册的用户将无法通过 Passport 登录。已成功关联后新注册的用户无此问题。

在开启了 Discuz! 通行证后,您仍然可以通过 logging.php?action=login 这个链接来登录论坛,以备调试之用,但页面上显示的链接将改为应用程序的登录 URL。注意:开启通行证后,建议您通过 Discuz! 选项关闭论坛本身的注册功能,以免用户通过论坛注册而产生无法同步的问题。

您可以在 Discuz! 的 api/passport.php 找到 Discuz! Passport 的全部源程序,您也许通过他更好的理解 Passport 的原理,更快的完成应用程序与Discuz! 之间的整合。

典型错误提示

Illegal request

非法请求,当验证字串 verify 不匹配时会产生此提示。可能是应用程序与 Discuz! 配置的私有密匙不同,或是通过 URL 传递前,未将必要的参数(如 auth、forward 等)进行 URL 编码,也有可能是使用了经过 URL 编码的参数值用来计算 verify 的 md5 值造成。以 PHP 语言为例,正确的代码应当是类似于的如下的格式:

Lack of required parameters

auth 内容解密后,缺少必要的信息 time、username、password、email。

Request expired

请求过期。当前服务器时间与应用程序提交过来的 time 之差大于 Discuz! Passport 中设置的请求有效期。可能是使用以往的代码非法尝试,也可能是由于应用程序和 Discuz! 论坛所在的两台服务器,时间设置有误造成。

Invalid action

没有指定 Passport 所执行的 action。

真正的尊敬,既不属于那些批评别人头头是道的人,也不是属于给强人指出过错、指点别人哪里做的不好的人。真正的尊敬,是属于那些勇于亲身投入战场,脸上沾满了尘土、汗水和鲜血的奋斗者们。他们坚持不懈的努力,尽管曾经犯下错误,并一再失败,但他们满怀激情,执著不懈,将生命奉献于崇高的事业。他们为经过艰辛努力最终取得的伟大成就而自豪,如果失败,他们也败得荣耀。因此,那些既没赢得过胜利,也没懂得什么叫做失败的,冷漠、胆怯的灵魂,是永远也无法与这些真正值得尊敬的人相提并论的。
http://www.cnedwin.com

TOP

发新话题