Discuz为某签到插件添加验证码(1/2 添加DZ自带验证码)

我们在做或者修改一些特殊类型的插件(比如签到)的时候,可能会被一些开签到机的所困扰,最好的办法就是增加验证码了。
本文章将分为两个部分,第一部分为添加普通的dz自带的验证码,第二部分为调用极验插件,让签到插件支持极验。

范例插件:https://addon.discuz.com/?@dc_signin.plugin

你所需要了解的内容:
PHP的基本语法

Discuz的模板特殊语法:https://open.discuz.net/?ac=document&page=template_coderule

0.准备
首先,我们要先了解到dz的表单验证机制。每个表单都会生成一个独一无二的formhash来对页面来源性进行验证。怎么验证呢?dz提供了一个submitcheck的方法,用来对提交的表单进行检查来源是否合法。

function submitcheck($var, $allowget = 0, $seccodecheck = 0, $secqaacheck = 0)

submitcheck拥有四个参数

    $var : 全局变量中的下标,string类型
    $allowget : 是否允许以get的方式请求,0为不允许,1为允许
    $seccodecheck : 是否验证验证码,0为不验证,1为验证
    $secqaacheck : 是否验证安全问答,0为不验证,1为验证

很明显,为了验证验证码,我们需要把第三个参数$seccodecheck设置为1,就可以使用验证码验证了。

其次,我们需要为插件需要提交表单的页面,添加一个输入验证码的输入框
我们可以参考一下dz自带的登录页面的验证码的实现

<!--{if $seccodecheck}-->
<!--{block sectpl}--><div class="rfm"><table><tr><th><sec>: </th><td><sec><br /><sec></td></tr></table></div><!--{/block}-->
<!--{subtemplate common/seccheck}-->
<!--{/if}-->

在这之前,我相信你应该已经读过了Discuz的模板特殊语法的文档了吧。什么?没有?回到文章顶部,找到文档地址,赶紧去读吧,至少你需要先了解<–{if}–>这个特殊语法。

首先,dz会判断你是否启用了验证码功能,如果启用了,就会开始输出第二行,直到if的闭合
最关键的就是第三句,他将会调用你当前模板的common/seccheck页面,也就是验证码页面。
所以我们可以依葫芦画瓢,只需要把判断改为自己的即可(比如你插件自己的配置啊,甚至直接不要这个判断也可以。)

1.开始改造
首先我们要找到范例插件的签到提交表单验证的位置。该插件的提交验证的地方在sign.inc.php中

那么我们首先要做的就是先写一个$seccodecheck变量(为了到时候给添加极验验证方便取消默认的验证码),赋值为1
然后修改之前的那个submitcheck,为他的第三个参数添加我们刚才写的$seccodecheck变量(第二个你就写为0就行了)。
此处要提一个可能存在的Bug,在dz的部分版本中,可能还需要你在判断中手动再写一个验证码验证方法。我仅在我自己的开发环境碰到过这个Bug,不确定是什么原因导致的。

if(!check_seccode($_G['gp_seccodeverify'], $_G['gp_sechash'])){
showmessage('submit_seccode_invalid');
}


至此,后台的改造我们就已经完成了。

接下来我们需要修改前台的表单页面,为他增加一个验证码输入框。
该插件的签到提交页面在插件目录下的template/sign.htm(电脑版)与template/touch/sign.htm(手机版)中,我们都需要进行修改。
首先我们需要先找到提交按钮(type=”submit”的button控件),然后在他的上方添加验证码代码。你可以直接使用登录页面的代码,也可以使用我目前所使用的。(如果你使用登录页面的那个验证码代码,请注意判断。请仔细阅读我之前的0.准备)

<!--{block sectpl}--><sec> <span id="sec<hash>" onclick="showMenu(this.id)"><sec></span><div id="sec<hash>_menu" class="p_pop p_opt" style="display:none"><sec></div><!--{/block}-->
<!--{eval $seccodecheck = 1;}-->
<!--{block sectpl}--><div class="rfm" style="width:auto"><table><tr><th><span class="rq">*</span><sec>: </th><td><sec><br /><sec></td></tr></table></div><!--{/block}-->
<!--{subtemplate common/seccheck}-->

那么,准备好见证奇迹吧!进入签到页面,点击签到

那么,我们就已经完成了我们的第一步,为插件添加Discuz自带的验证码。
在下一节,我们将会利用这个插件自带的附件机制,为签到插件添加极验的验证。

Vysor 2.0.9 汉化与破解版(2018/12/14)

声明:这个项目仅为个人学习JavaScript逆向方面的知识用,禁止用作商业用途,不允许任何网站转载。
也希望你能够至少购买至少1个月支持原作者

等我有空了我再发布破解的方法

注意,部分Android机如小米需要开启开发者选项中的USB调试(安全设置) 选项才可以使用远程操控。
部分较老的机型无法使用较高的解析度,否则可能会花屏

最近升职了,工作上事儿开始变多了,所以更新的不是很及时,很抱歉

汉化无破解版文件:
https://pan.baidu.com/s/1I5hxA3tXxUHRx2dJZ0aH4g

汉化破解版:
链接: https://pan.baidu.com/s/1nVzFVdF5Wuvn5QQP5fdNsQ 提取码: 89p5

食用方法:
Chrome版:
先打开扩展程序,找到Vysor,然后看看他的ID是多少

在地址栏输入chrome://version ,看看你的个人资料路径在哪儿

复制上面的 个人资料路径 到文件资源管理器中,然后打开进入Extensions目录,再找到刚才Vysor的ID名对应的文件夹,再打开2.0.9_0,将压缩包内的所有文件复制进去覆盖掉即可。

这次已经把提示语进一步汉化了,还有少部分界面没翻译到是因为我不知道那个界面是干嘛的。
中文翻译好麻烦啊好麻烦啊好麻烦啊(摇晃)

Discuz 模拟登录踩坑心得

通过两天的踩坑,终于搞定了Discuz的登录模拟
其中最大的坑为Cookie,在进行传递验证码等操作的时候也必须要使用相同的Cookie,否则就会导致因为Cookie变化,然后formhash也跟着变化,最后传递formhash的时候回出现非法参数的问题
其次是关于验证码,Dz的这个验证码是真的蛋疼。

 

1.获得seccode,formhash与loginhash参数
首先我们要爬取论坛登录页面的html代码,然后获得这三个参数,可以通过正则的方式
登录页面地址一般为DzUrl + /member.php?mod=logging&action=login
然后分别获取seccode,formhash与loginhash参数,以下是我个人获取这几个参数时用的正则
seccode: (?<=seccode_)([^\"]*)
loginhash: (?<=loginhash=)([^\"]*)
formhash: (?<=<input type=\"hidden\" name=\"formhash\" value=\")([^\"]*)

同时,非常重要的一点,后面的每一步都要保存你的Cookie!然后每次访问的时候,请带上上一次保存的Cookie
(我讨厌正则)

2.刷新并获取验证码
这里要用到我们刚才获取到的seccode了,验证码的刷新地址一般为DzUrl + /misc.php?mod=seccode&action=update&idhash={你的seccode值}
(再次提醒,请带上Cookie)

然后会返回一个JavaScript代码,然后我们需要获取那个验证码图片的地址了,我使用的是正则表达式
(?<=width=\"\\d{3}\" height=\"\\d{2}\" src=\")([^\"]*)

获得图片地址后,我们只能使用下载文件流的方式来下载验证码图片,比如你使用桌面开发的话,直接设置图片地址为上面获取到的地址,是没用的

在获得验证码图片,并用户输入验证码后,我们可以来验证一下该验证码是否正确
验证码验证地址为DzUrl+ /misc.php?mod=seccode&action=check&inajax=1&modid=member::logging&idhash={你的seccode}&secverify=验证码

然后会返回一个XML,验证通过的话则会返回

3.提交登录信息
提交登录用的地址为DzUrl + /member.php?mod=logging&action=login&loginsubmit=yes&loginhash={你的loginhash}&inajax=1
提交的方式为POST,ContentTypeapplication/x-www-form-urlencoded
然后POST以下包
formhash={formhash}&referer={论坛地址,请使用urlencode编码}%2F.%2F&loginfield={登录方式,默认用username,如果论坛支持其他方式登录(比如邮箱的参数为email)可以手动修改此参数}&username={用户名,请使用urlencode编码}&password={密码,请使用urlencode编码}&questionid={问题编号,如没有,请设置为0}&answer={登录密码问题答案,如没有,请留空}&seccodehash={seccode}&seccodemodid=member%3A%3Alogging&seccodeverify={验证码code}

然后就会返回登录信息,再把Cookie保存下来就行。

修复Dz在Chrome浏览器浏览器无法刷新浏览器的问题

前段时间老司机帮我们给论坛升级为https,但是出现了验证码刷新不出来的问题。

后来用F12检查,提示如下错误

Refused to execute script from ‘https://www.xxx.com/misc.php?mod=seccode&action=update&idhash=xxxxxxxxxx&modid=member::register’ because its MIME type (‘text/html’) is not executable, and strict MIME type checking is enabled.

后来上网查了一下,其实是最近Chrome的更新,将会对文件类型的检查更为严格,如果文件类型不一致,将无法加载。

解决方法也很简单

进入”<DiscuzRoot>/source/module/misc/” 目录,打开misc_seccode.php,然后找到63行,内容为


echo <<<EOF
if($('$showid')) {
if(!$('v$showid')) {
var sectpl = seccheck_tpl['$idhash'] != '' ? seccheck_tpl['$idhash'].replace(/<hash>/g, 'code$idhash') : '';
var sectplcode = sectpl != '' ? sectpl.split('<sec>') : Array('<br />',': ','<br />','');
var string = '<input name="seccodehash" type="hidden" value="$idhash" /><input name="seccodemodid" type="hidden" value="$modid" />' + sectplcode[0] + '$seclang[seccode]' + sectplcode[1] + '<input name="seccodeverify" id="seccodeverify_$idhash" type="text" autocomplete="off" style="{$imemode}width:100px" class="txt px vm" onblur="checksec(\'code\', \'$idhash\', 0, null, \'$modid\')" />' +
' <a href="javascript:;" onclick="updateseccode(\'$idhash\');doane(event);" class="xi2">$seclang[seccode_update]</a>' +
'<span id="checkseccodeverify_$idhash"><img src="' + STATICURL + 'image/common/none.gif" width="16" height="16" class="vm" /></span>' +
sectplcode[2] + '<span id="v$showid">$message</span>' + sectplcode[3];
evalscript(string);
$('$showid').innerHTML = string;
} else {
var string = '$message';
evalscript(string);
$('v$showid').innerHTML = string;
}
$htmlcode
}
EOF;

在echo上一行加上

header('Content-Type: text/javascript');

即可解决。

2016/12/13杂谈

不知道写点什么,最近过得好吗?

感觉最近两年突然变得懒散起来了,完全学不进去东西了,估计前两年已经是我学习的巅峰期了吧(苦笑)。

言归正传,打算这个月学点儿有价值的东西,计划如下:

1.JavaScript基础+Node.Js基础

2.英语AB级基础

3.html基础

 

该动起来了

WPF在XP出现System.Windows.Markup.XamlParseException异常

可以,这很XP。

首先整理一下思路,恩,错误很明显了,Xaml的问题,于是乎把MainWindow清空,然后再测试。

等下,还是崩溃?还是一样的错误?

尝试谷歌了一圈回来,都没找到好的答案

直到看到这个问题

http://stackoverflow.com/questions/2481178/xamlparseexception-on-windows-xp

其中有提到在XP下Image可能会不兼容ico图标的情况

等等,图标,XP好像不支持256x大小的ico来着?

于是乎去掉程序图标,顺利运行。

不说了,我先去买点儿吃的庆祝下(嘿嘿)

WPF引用字体文件

很早以前就希望给BakaXL添加自定义字体功能了,但是查阅了很多资料,到国外也去搜了一圈,都没有搜到相关资料。

最终在MSDN的一个页面找到了解决方案

https://msdn.microsoft.com/zh-cn/library/system.windows.media.fontfamily(v=vs.100).aspx

字体的友好名称还可以指定相对URI 值,该值需要基URI 才能解析字体引用。 FontFamily 对象的 BaseUri 属性对应于基URI 值。

OK!果然还是万能的MSDN靠得住!代码很简单,一行就能搞定

控件名.FontFamily = new FontFamily(new Uri("file:///d:/temp/"), "./#字体名字");

效果也是棒棒的

1

2

嗯,还能解决一群插屁(XP)用户使用那个丑到爆的宋体字体问题。

有事儿没事儿先翻MSDN!

说起来……已经好久都没写过博客了……

WPF仿QQ启动时渐变动画

感谢基友Xblack提供方法。

主要用到的就是OpacityMask,通过OpacityMask来设置不透明模板,然后使用Triggers控制动画。源码如下

 


<Window.OpacityMask>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop x:Name="StopX" Color="Black" Offset="0"/>
<GradientStop x:Name="StopY" Offset="1"/>
<GradientStop Offset="1"/>
</LinearGradientBrush>
</Window.OpacityMask>
<Window.Triggers>
<EventTrigger SourceName="Window" RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard TargetName="StopX" TargetProperty="Offset">
<DoubleAnimation From="0" To="1" BeginTime="0:0:0.05" Duration="0:0:0.25"/>
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard TargetName="StopY" TargetProperty="Offset">
<DoubleAnimation From="0" To="1" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>