彼岸网

 找回密码
 立即注册
搜索
热搜: 活动

tag 标签: 管理员

相关帖子

版块 作者 回复/查看 最后发表

没有相关内容

相关日志

分享 分析Discuz系统安装后无法登录UCenter问题
热度 2 天香公主 2016-12-10 01:32 AM
分析Discuz系统安装后无法登录UCenter问题
最近遇到了一个奇怪的Discuz/UCenter问题。我在服务商namecheap提供的测试网站上全新安装的Discuz 3.2 系统里登录管理中心后,点击最后一个tab来登录与Discuz一同安装的UCenter出现问题,几乎每次填写了UCenter创始人的密码(就是在安装Discuz设的管理员密码)后点击登录后又回到了该登录页。但如果不断的重复登录的话,多试几次也会有一次成功,但是进去后点击网页上任何链接后就又被推回了登录页。而在我自己本地机器上安装的Discuz/UCenter里则从无这类问题。这是怎么回事呢? 让我们先来查下有关代码。在填写了UCenter创始人密码点击登录后,向服务器发送的请求是 admin.php?m=usera=login 最终检查密码正确性的代码在文件 uc_server/control/admin/user.php 里的函数 control.onlogin 中,其中关键部分是在确认了用户提供的密码是正确的后从用户名(如果是创始人的话,用户名自动定为UCenterAdministrator)产生了一个 sid(估计意为 session id): xmp { white-space: pre-wrap; display: block; border: 1px solid lightgrey; padding: 5px;} sid)); exit; 这些代码表明 sid 被同时放入了 query string 和 cookie 中。以图中的数据为例: query string 中的 sid: f70blEiCdTNvsQpCEXhME6PPP9dSXxCg5W9kFeISvc9K11%2FjGmcOPPyrtfYymtqKVMXuBBlsOi5GNw cookie 中的 sid: f70blEiCdTNvsQpCEXhME6PPP9dSXxCg5W9kFeISvc9K11%252FjGmcOPPyrtfYymtqKVMXuBBlsOi5GNw 两者有个细微的差别,前者有的 % 在后者里变成了 %25。其原因是代码用的设置的办法是基于PHP的 setcookie 函数,它自动将提供的内容做了一次 url 编码( 链接 ): Note that the value portion of the cookie will automatically be urlencoded when you send the cookie, and when it is received, it is automatically decoded and assigned to a variable by the same name as the cookie name. If you don't want this, you can use setrawcookie() instead if you are using PHP 5. 当用户登录成功后,服务器端的代码向客户端发送了一个redirect指令。这样客户端接受了cookie后向服务器端发了一个query string和cookie中都带着sid(但有上面提到的细微差别)的请求 admin.php?m=framea=mainiframe=1sid=..., 在服务器收到这个请求后会检查发送过来的sid从中找到用户名。但在这一步上Discuz出了问题,没能找到用户名。问题出来哪里呢?让我们看一下相关的代码,在文件 uc_server/model/admin.php里的adminbase类中: sid_decode($sid) ? $sid : ''; ... } 其中函数 getgpc 的定义是 function getgpc($k, $t='R') { switch($t) { case 'P': $var = &$_POST; break; case 'G': $var = &$_GET; break; case 'C': $var = &$_COOKIE; break; case 'R': $var = &$_REQUEST; break; } return isset($var ) ? (is_array($var ) ? $var : trim($var )) : NULL; } 函数 adminbase 中的第三句说的是如果变量cookie_status的值非零,则从cookie (即 $_COOKIE)里得到sid,不然就从请求(即 $_REQUEST)里经一次 url 解码后得到sid。由于$_COOKIE在赋值时已经经过一次 url 解码,所以 getgpc('sid', 'C') 给出的是前面产生的sid,以上面的例子为例,就是 f70blEiCdTNvsQpCEXhME6PPP9dSXxCg5W9kFeISvc9K11%2FjGmcOPPyrtfYymtqKVMXuBBlsOi5GNw。那么 rawurlencode(getgpc('sid', 'R')) 是不是也给出同样的值呢?这取决于getgpc('sid', 'R') (即 $_REQUEST )是不是 f70blEiCdTNvsQpCEXhME6PPP9dSXxCg5W9kFeISvc9K11/jGmcOPPyrtfYymtqKVMXuBBlsOi5GNw。由于 $_REQUEST 在赋值时也经过一次 url 解码,所以 $_REQUEST 如果从 query string 里取值的话就能得到预期的结果,但是如果从 cookie 里取值的话就会得到错误的值 f70blEiCdTNvsQpCEXhME6PPP9dSXxCg5W9kFeISvc9K11%2FjGmcOPPyrtfYymtqKVMXuBBlsOi5GNw。 经检查发现在我的namecheap服务器上总是从cookie取得,而在我本地机器上总是从query string取得。这就是在服务器上出现问题的原因。它导致了后面使用sid_decode是得不到用户名,从而将登录用户重新带回了登录页。那么为什么在不同机器上有不同行为呢?或者说 $_REQUEST 在 cookie 和 query string 有同名变量时,应该从何者取值呢?从PHP手册 ( 链接 ) 看是这样说的: 这个次序取决于PHP设置文件 php.ini 里 variables_order 的值,如果这个值没定义的话,则取决于另一个变量 request_order 的值。 request_order string: This directive describes the order in which PHP registers GET, POST and Cookie variables into the _REQUEST array. Registration is done from left to right, newer values override older values. If this directive is not set, variables_order is used for $_REQUEST contents. 检查我的本地机器上的设置发现 request_order 是GP,所以 $_REQUEST 从 query string (即G)得到了sid。而检查我的namecheap服务器的设置发现 request_order无定义而 variables_order 的值是EGPCS,所以 $_REQUEST 从 cookie (即C)得到了sid。 故而解决办法是将前述那段代码里的第三句 cookie_status ? getgpc('sid', 'C') : rawurlencode(getgpc('sid', 'R')); 改为 cookie_status ? getgpc('sid', 'C') : rawurlencode(getgpc('sid', 'G')); 或者更保险点 cookie_status ? getgpc('sid', 'C') : (getgpc('sid', 'G')?rawurlencode(getgpc('sid', 'G')):getgpc('sid', 'C')); 网上有些帖子建议了另一种解决办法(如 链接 ),将函数 adminbase 里的第二句 cookie_status = 0; 改为 cookie_status = isset($_COOKIE ) ? 1 : 0; (而不改第三句),即将函数 adminbase 改为 sid_decode($sid) ? $sid : ''; ... } 这个代码正是单独下载的UCenter软件里的对应代码。这个改动说的是如果浏览器支持cookie(并且设置项variables_order里含有C)的话就从cookie里取sid,不支持的话就从query string里取sid (而改动前的意思是不管浏览器是否支持cookie,都从 query string 里取sid)。这种解决办法其实是有个前提就是浏览器支持cookie。不然的话还是会遇到我前面指出的问题从而仍然无法登录。所以这种改法还应该将第三句里的 'R' 改成 'G'。 当然一个网站要解决这个问题也可以不改代码而修改PHP设置里前述两个设置项的值。 另外为何用户如果不断尝试登陆最终还是能成功进去,但进去后点击任何链接就又被退回到登陆页?登陆成功是因为那次的 sid 里没有任何经 url 编码会变化的字符,因而那个 bug 就没起作用。如下图 但是登陆成功后并不是一劳永逸,因为下面的代码表明每次发送回复时有会产生新的 sid,而且它赋在了网页上每个链接路经的 query string上,而这个新的 sid 很有可能是含有在 url 编码下会变化的字符,所以点击后由于前述 bug就被推出来了。
个人分类: Discuz|2728 次阅读|4 个评论
分享 网站规则具体执行细则
admin 2016-4-3 11:03 PM
被删除的内容不再公开保留,如果是日志将存放在日志回收站,作为备案; 为便于管理员操作,举报者必须列出具体举报条目或提供链接; 管理员介入的操作(比如删除或设限制)将以评论的形式发布在本文下,原则上不另发文公告; 对任何操作的异议,管理员将同样在本文下答复; 上述细则自2016年4月3日起执行。
1441 次阅读|1 个评论
分享 Discuz插件发布纪要
热度 2 天香公主 2016-1-27 09:41 PM
Discuz插件发布纪要
近来对我以前写的日志搬家插件( 链接 )做了些改进,诸如允许管理员来帮用户搬家,保存原来博文的发布时间等,准备等成熟时放到Discuz官网的应用中心去。本文记录下在这过程中遇到的一些问题和解决方法。 在开发插件时,与插件有关的文件都在两个文件夹里。几乎所有与该插件相关的文件都在source/plugin下一个以该插件命名的子文件夹里,但语言包文件得放在data/plugindata下: td, th { vertical-align: top; } 而当安装该插件到使用它的网站上去时,所有与该插件相关的文件都放在了前述第一个文件夹里。这些文件包括了在开发时在这个文件夹里的所有文件,以及一个xml格式的设置文件。Discuz在开发状态下提供了产生一个设置文件的方法(称为导出),它包含了原来语言包里的所有内容,以及一些其它可设置的项目。 xmp { white-space: pre-wrap; display: block; border: 1px solid darkgrey; background-color: lightgrey; } 1。支持多个版本 从在开发状态下的Discuz网站上导出的xml设置文件,可以拷贝到安装插件的网站上直接使用如果两个网站使用的同样版本的Discuz软件。但要使得尽可能多的网站使用该插件,则需要对导出的文件做些修改。比如在3.1版的网站上安装用3.2版导出的文件时,就会看到下面的警告: 其原因是导出文件有下面这行 (假如开发网站所使用的Discuz的版本是3.2): 如果该插件经测试后确定可以用于3.1的网站的话,我们可以把这行改为 这样在安装时就不会出现上述警告了。 2。如何修改设置文件 那么如何来修改设置文件呢?这里讨论下用UTF-8版的情形。这个XML设置文件的特点是它是用没有标签(BOM)的UTF-8编码格式储存的,而它的表头上这写着编码用iso-8859-1编码: ... 所以 Notepad 不是一个合适的编辑工具,因为它在保存时会自动添加BOM(参见 链接 )。一种工具是 Visual Studio, 如果我们直接在Visual Studio里把设置文件打开的话会看到文件里的汉字都是乱码, 因为Visual Studio按XML表头的编码(iso-8859-1)来解码了。我们可以在这里修改文件和保存。但是如果要修改汉字的话,要按下述的方式来打开文件:在菜单上选择 Open-File, 在文件选择框里单击来选定要打开的设置文件,再点击Open With-XML(Text) Editor with Encoding- Choose "Unicode (UTF-8 without signature) - Codepage 65001) as Encoding: 另一种可用的工具是Notepad++。和上面解释过的同样原因,当文件打开时其中的汉字是乱码,要在菜单上选择Encoding-Encode in UTF-8后才能看到汉字。 在视窗系统下带BOM的设置文件也可正常使用,但在Linux下则会显示乱码。这就是为什么有时我在Notepad下修改了设置文件并测试后拷贝到Linux服务器上就出现乱码的原因。 3。允许管理员设置插件 有些使用插件的方式是需要安装插件的网站决定的。以我的日志搬家插件为例,有的网站也许会允许用户自行搬家,也有的网站也许希望由管理员来控制。所以我们要让使用该插件的网站来决定这些设置。在插件设计时,我们可以加入变量。在日志搬家插件里我加了两个按钮: 在使用该插件的网站上安装后就可以看到设置的地方: 那么如何来设置这些变量的缺省(default)值呢?在变量设计界面上并没有让你设缺省值的地方。事实上它用了设计网站上的设置处定的变量值作为了安装时变量的缺省值,这应该算是个自然的选择。如果要修改缺省值的话,可以改设计网站的设置,也可以改xml设置文件,这些变量也成了设置文件里的一部分(注意在下面的内容里第一个变量的缺省值是1,而第二个变量的缺省值是0): 那么插件是如何检查和利用这些变量的呢?下面是在脚本文件里使用的例子: $allowUserToImport = $_G ; if (!$allowUserToImport && $_G !=1) { showmessage(lang('plugin/txgz_blog_importer', 'import_deny')); } 4。支持多种语言和字符编码 Discuz软件应不同网站的需求提供了简体GBK, 简体UTF-8, 繁体BIG5, 和繁体UTF-8四种形式的软件。如何让我们的插件可以安装在使用所有这些形式的网站上呢?我们可以在供下载的文件夹里放这四种形式的xml文件,然后安装网站会根据这些文件的文件名来决定哪个是适用于该网站的xml设置文件: 如何来产生这四个xml文件呢?由于我是在简体UTF-8环境下开发的,汉字用在线软件( 链接 )来产生后加入了语言包(注意在保存语言包文件时应选择File-Advanced Save Options-Encoding: Unicode (UTF-8 without signature) - Codepage 65001,不然文件里的汉字保存后会变成问号),进而经导出产生了 discuz_plugin_txgz_blog_importer.xml,将导出文件做必要修改后可以改名为 discuz_plugin_txgz_blog_importer_SC_UTF8.xml。从简体UTF-8转繁体UTF-8可以用在线软件( 链接 ),由简体UTF-8转简体GBK,和由繁体UTF-8转繁体BIG5可以在Notepad+直接产生。比如在其中新加一个文件,在菜单上选择 Encoding-Character sets-Chinese-GB2312 (Simplified) 后,把简体UTF-8的内容拷贝上去,保存后就得到了简体GBK。 插件内的其它文件如PHP脚本文件,模板文件,JS脚本文件和风格文件都必须以ANSI编码储存才能同时被所有四种语言和字符编码系统使用。这也意味着插件中的JS脚本文件和风格文件不应含有任何汉字 (虽然Discuz软件里的个别JS脚本文件和风格文件含有汉字,但Discuz对每个系统提供了适合该系统的这些文件。现在我们要一套文件(除xml设置文件)适合所有系统,使用要求更为严格)。 如果是要将插件放到Discuz的应用中心上去,我们也可以不提供四个xml设置文件。而只提供一个名为discuz_plugin_txgz_blog_importer.xml的供简体GBK使用的xml文件,应用中心会自动产生这四个xml文件。 插件下载: http://www.bian-wang.com/upload/txgz_blog_importer_160406.zip 4/16/2016 补充:看到Discuz网站上的一个讨论( 链接 )给出了一个在插件中的javascript文件里使用语言包汉字的很好的解决方法:在html文件里调用语言包里的汉字来定义javascript变量值,而在javascript文件里调用这些变量。
个人分类: Discuz|2977 次阅读|5 个评论

小黑屋|Archiver|彼岸网  

Powered by Discuz! X3.1 © 2001-2014 Comsenz Inc.
GMT-4, 2026-6-23 09:51 PM , Processed in 0.027960 second(s), 15 queries.

返回顶部