PC端登录需要在微信开放平台申请,而移动端授权登录只需要有已经认证的服务号即可。然后同一个网站平台,用同一个微信用户去登录,会发现PC端获取的微信用户openid和移动端不同,这个问题如何解决?
一、官方做法
我们需要在微信开放平台绑定微信服务号,这个时候就有一个奇葩的事情出现,如果该微信服务号没有申请微信小程序,那么微信开放平台提示必须先开通小程序。
那么在微信开放平台绑定微信服务号后,我们就可以获取到统一的一个UnionID,这个UnionID无论是Pc端微信登录还是移动端微信登录,都是统一的。
我们看下官方的解释:
UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的。
二、另辟蹊径的做法
场景1、
1、手机号注册-》成功。
2、该用户第一次使用PC端微信登陆,则到达绑定手机号页面,如果该手机号已经注册,则更新数据表字段weixin_open_id。
3、该用户第二次使用PC端微信登陆,更新最后一次登录时间。
场景2、
1、手机号注册-》成功。
2、该用户第一次使用移动端微信登陆,则到达绑定手机号页面,如果该手机号已经注册,则更新数据表字段weixin_open_id_m。
3、该用户第二次使用移动端微信登陆,更新最后一次登录时间。
场景3、
1、该用户第一次使用PC端微信登陆,则到达绑定手机号页面,绑定手机号,插入记录。
2、该用户第二次使用PC端微信登陆,更新最后一次登录时间。
场景4、
1、该用户第一次使用移动端微信登陆,则到达绑定手机号页面,绑定手机号,插入记录。
2、该用户第二次使用移动端微信登陆,更新最后一次登录时间。
总之,无论用户第一次是手机号注册还是PC端微信登陆、移动端微信登陆,只要是第一次登陆,我们都会拿到用户的手机号,那么手机号作为该用户凭证。
三、需要注意
我们可以用如下代码判断是PC微信登录还是移动端微信登录:
if(request()->isMobile()){//移动端}else{ //PC端}
PC微信登录和移动端微信登录需要分别处理。
最后
我们还是建议大家用官方做法,如果遇到某些情况可以使用第二种。另外对于大型网站来说,PC端和移动端单独分开,不适合自适应网站开发。
今天写了一个第三方登录的功能,使用的是钉钉,实现的功能就是打开网页,使用的钉钉APP扫描二维码,快捷登录网站,下面一起来看一下!
钉钉开放平台
首先,登录管理后台,点击右上角进行登录,这里的登录需要是管理员身份或者授权权限的子管理员身份,其他的身份不好使,如果没有管理员身份或子管理员身份(如我一样),那么就只能自己创建一个团队了,里面邀请了好友就可以了。这样你就是拥有管理员身份了。继而可以登录这个管理后台了(第一次登录需要设置个密码,后续登录时需要输入的)。
钉钉创建应用
进入管理页面后,我们进入应用开发菜单,找到最下方的“移动接入应用”,进入子级菜单中的“登录”,在里面创建一个应用。如下图:
创建应用创建应用后,回到页面中,我们可以看到 appid 和 appSecret 这两项参数,后续我们会用到。
授权流程
第三方发起钉钉授权登录请求,钉钉用户允许授权第三方应用后,钉钉会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数。通过code调用接口getuserinfo_bycode获取授权登录用户信息。
流程图构造扫码登录页面
构建登录页面有两种方式,我们以跳转方式为例,这种方式使用得较多,也非常方便。在企业Web系统里,用户点击使用钉钉扫描登录,第三方Web系统跳转到如下地址:地址就不做展示了,说一下地址的参数:
获取用户信息
首先说一下,我们获取到的用户信息只有三项,如下表:
但是在下午的实际测试中发现,接口返回的值还多了两项,文档中没有做出说明,猜测是权限字段和权限标识字段。
在获取用户信息时我们要使用到的参数有如下:
在请求的时候需要使用POST方式并传递数据,数据如下:
{"tmp_auth_code": "23152698ea18304da4d0ce1xxxxx"}
这里需要注意一点,传递数据为json格式,如果使用CURL进行请求时会出现post请求数据格式错误的提示,我们需要在curl请求头上面做出说明,代码如下:
$header = [ "Content-Type: application/json; charset=utf-8", "Content-Length:" . strlen(json_encode($postFields)) ];
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
这样才能正常的发送请求信息,需要代码的童鞋可以找我!
0x00 前言
最近刷题碰到好几个关于php代码审计中session相关的问题,之前没有做过系统的总结,在此补一下锅。
0x01 Session基础知识
这里主要讲讲传统的PHP中的“服务端Session”。至于什么是服务端Session,什么是客户端Session,可以看看P神的**客户端 session 导致的安全问题https://www.leavesongs.com/PENETRATION/client-session-security.html
Session概念:在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。
Session机制:session内容一般以文件的形式存储于服务器中,而本地浏览器会存储一个与服务器中session文件对应的Cookie值,Cookie存储的是键值为“PHPSESSID”的Seeion_id值,用户在访问web应用时,每次跳转发生http请求时,会自动把这个存储session_id的Cookie值发送过去,因此web应用的所有页面都可以获取到这个SESSION_ID值,也就可以通过session_id获取服务器中存储的session值,当用户关闭浏览器后,cookie存储的session_id自动清除,一般服务器存储的session文件也会在30分钟后自动清除。
比如在wamp环境下,index.php如下:
<?php
session_start();
phpinfo();
?>
首先理解一下session_start()
当会话自动开始或者通过 session_start() 手动开始的时候, PHP 内部会依据客户端传来的PHPSESSID来获取现有的对应的会话数据(即session文件), PHP 会自动反序列化session文件的内容,并将之填充到 $_SESSION 超级全局变量中。如果不存在对应的会话数据,则创建名为sess_PHPSES SID(客户端传来的)的文件。如果客户端未发送PHPSESSID,则创建一个由32个字母组成的PHPSESSID,并返回set-cookie。
可以看到请求中对应的PHPSESSID:ifrvi9r7ui81r0fjq569b06862
在服务器端,即/wamp/tmp下我们就可以发现一个生成的记录Session的文件,因为也没有记录什么会话信息,因此该文件是一个空文件。
补充一下关于php-Session相关配置的说明
在php.ini中对Session存在许多配置,这里我们通过phpinfo来说明几个重要的点。
说明如下:
session.save_path="" --设置session的存储路径
session.save_handler="" --设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式),默认files以文件存储
session.auto_start boolen --指定会话模块是否在请求开始时启动一个会话,默认为0不启动
session.serialize_handler string --定义用来序列化/
常见的php-session存放位置
/var/lib/php5/sess_PHPSESSID/var/lib/php7/sess_PHPSESSID/var/lib/php/sess_PHPSESSID/tmp/sess_PHPSESSID/tmp/sessions/sess_PHPSESSED0x02 Session可能导致的攻击面
Session序列化攻击Session文件包含Session伪造用户登录Session逻辑漏洞0x03 Session序列化攻击
Serialize_handler
要了解Session序列化攻击,先来了解一下Session机制中对序列化是如何处理的。
在php中存在三种序列化处理引擎
本地测试如下:
Session文件内容分别对应结果为
test|s:7:"CoCo1er";
<0x04>tests:7:"CoCo1er";
a:1:{s:4:"test";s:7:"CoCo1er";}
攻击利用原理
payload千万条,原理第一条。
(这里补充说一点,PHP中的Session的实现是没有的问题,危害主要是由于程序员的Session使用不当而引起的。如下)
使用不同引擎来处理session文件
如果在PHP在反序列化存储的$_SESSION数据时使用的引擎和序列化使用的引擎不一样,会导致数据无法正确第反序列化。通过精心构造的数据包,就可以绕过程序的验证或者是执行一些系统的方法。例如:
在这么一种情况下:
假如我们使用php_serialize引擎时进行数据存储时的序列化,可以得到内容
$_SESSION[‘key’] = ‘Boby’;
a:1:{s:3:”key”;s:4:”Boby”;}
这时我们的解析采用了另一种引擎:php
思考一下这时会发生什么情况?(php引擎中以竖线来分隔键和值)
如果像上面我们的payload换一下,传入内容以及得到的存储内容如下:
$_SESSION['key'] = '|O:4:"User":0:{}';
a:1:{s:3:"key";s:16:"|O:4:"User":0:{}";}
这时候a:1:{s:3:"key";s:16:"被当作了key,而后续的O:4:"User":0:{}";}被当作了value从而被反序列化。这里可能有人会问了,为什么会被反序列化?
看看官方文档
这里可能还会有人问?那串value不符合"正常"的被反序列化的字符串规则。这个也不用担心,这里提到一个unserialize的特性,之前也做题也遇到过。在执行unserialize的时候,如果字符串前面满足了可被反序列化的规则即后续的不规则字符会被忽略。
如果不太好理解不如直接来看一个在线测试用例:
总结一下,在php以php_serialize引擎生成session,然而又以php引擎来解析时,我们通过传入类似
$_SESSION[‘name’] = |序列化内容
这种形式的payload即有可能触发反序列化漏洞。当然这里只是提到了能够找到反序列化利用的点,至于能不能真正触发反序列化漏洞还需要结合当前环境以及一些魔术函数中是否存在可利用点。这就涉及到php反序列化漏洞的利用知识点了,这里也就不详细讲了。关于Session反序列化攻击的复杂利用方式,可以参考2018LCTF中的bestphp’s revenge一题。
没有$_SESSION变量赋值
从上面的情况中我们可以发现我们对session的赋值可控。那如果代码中不存在对$_SESSION变量赋值的情况下如何利用呢?来看下面一个点。
php还存在一个upload_process机制,即自动在$_SESSION中创建一个键值对,值中刚好存在用户可控的部分。
写入的方式主要是利用PHP中Session Upload Progress来进行设置,具体为,在上传文件时,如果POST一个名为PHP_SESSION_UPLOAD_PROGRESS的变量,就可以将filename的值赋值到session中。
//上传表单
<form action="http://xx.xxx.xx.xx/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" />
</form>
既然filename字段能够写入session中那么就满足了session可控条件,后续的利用条件同上面所述的情景一致,两种不同引擎先后作用导致了恶意的序列化字符串被解析。
0x04 Session文件包含
这个也是一个比较旧的知识点了,其实不仅是Session文件包含,仔细想想,理论上只要能够在文件中写入php代码,再被include包含进来不都可以实现getshell嘛?只不过在这里我们的可控点是Session文件,如果能向其中写入php代码,也是可以实现文件包含漏洞利用的。
作为文件包含的利用这里就不展示了,网上关于这个的基础资料早就烂大街了。
值得一提的是,往往现在的CTF出题不会仅限于文件包含这一个点来出题,而是利用诸如session+lfi的形式来入题获取源码等。而且可能加入open_basedir来限制路径,此时就需要熟悉了解session的机制,通过函数来改变save路径来利用。这个思路是在XCTF Final中出现的bestphp一题中的考点。感兴趣的同学可以去找到环境复现一波。
0x05 Session伪造用户登录
前几天正好3CTF出了一个这个考点,这里以那个题目来说明一下利用方式。(由于没有提供复现环境,此处也只能限于“纸上谈兵”,希望大家能够理解一下利用原理即可。)
**利用前提:**session可控;知道session存储格式。
这里的考题是多个攻击面的组合。题面index.php下提示要以admin登录。
sql盲注可以跑sqlmap拿到执行shellsql root用户存在file权限,但是往站点直接写shell无法成功(猜测应该是站点根目录有限制,但是可以猜测/tmp可写扫后台发现test.php,访问发现回显了session的数据结构Array([username]=>test),知道了session的格式。key为username,至于采用了哪种序列化引擎?三种都测一下就完事。这里满足了两个利用前提。通过sqlmap-shell往/tmp写入文件伪造adminpayload:select 'username|s:5:"admin";' into outfile '/tmp/sess_PHPSESSID'最后修改成对应设计的PHPSESSID即可伪造admin登录拿到flag。0x06 Session逻辑漏洞
很遗憾这个点也没有可以复现的环境。(官方买断...)这个是上两周unctf中出现的一道web题考点。这个逻辑漏洞处在重置密码处。过程大致如下。
密码重置分为三个步骤。
填写需要重置的用户名用户名绑定的邮箱中收到验证码填写验证码,进入重置密码页面,填写完新密码完成重置。这里存在的逻辑漏洞在于第一个页面的填写用户名处,猜测后台有设置session。类似:$_SESSION[‘name’] = $_POST['name'];
利用方式:重置admin密码。
打开一个正常页面完整流程走到最后一步,填写完验证码通过后,填写新密码,此时并不提交。新开另外一个页面完成第一步,重置用户填写admin,此时Session不再是我们之前自己的用户,而变成了admin。这时完成之前页面的提交。成功重置admin密码。这里逻辑漏洞产生的原因在于对填写验证码后没有对相关用户绑定做记录,在最后一步重置密码时没有对Session的可靠性进行检查就直接执行了功能。而我们都知道Session存储在服务器端,因此我们再开一个页面即可完成对单一session文件内容的修改(保证在同一个PHPSEEID下)。
0x07 总结
这里仅仅是记录了自己关于PHP的session机制相关的学习,举的都是自己最近在CTF题中接触到的点,但关于session的利用点怎么可能只有这几个?遇到了再补充学习吧。限于篇幅没有展开讲拓展利用,但是说白了,拓展利用就是多个复杂知识点的综合。我认为只有把原理性的问题搞清楚了才有可能去理解复杂的组合攻击。另外如果文中有什么理解表达错误的地方还望师傅们指正。
新浪微博是个很火的社交平台,有很多的名人在使用,今天我们我们来说一下用,用新浪微博登陆自己的网站。我们是用php来开发
首先要注册新浪的微博的开放平台或者是已有的账号登陆到这个平台,我是账号我直接来申请应用,填写相应的信息。
填写相应的信息,提交审核,我这个是我是申请通过的,现在申请需要三个工作日来审核,审核通过以后得到Key值和Secret值
我们通过网页授权拉去,用户信息审核中我们可以用测试账号来,来开发网站应用,要设置授权回调页面
下面我通过官方提供的开发文档,一步步实现自己的网站登录。我们第一步先获取code,通过code来拉去Token
通过获取到的Token和UID来拉去用户信息
获取到的用户信息我们来做处理,把自己的有用的存储到数据库。
这样我们就基本完成了登录,我们来测试一下是不是可以用新浪微博来登录
可以使用二维码扫描登录,也可以输入用户名和密码
由于工作需要将一个在linux端运行的软件可视化,打算基于web的形式将其可视化。带来的问题是如何跨平台无缝衔接web和linux中的软件,有幸的看到一个方法,利用ssh2技术即可实现我的需求。下面提供我的案例:
首先在linux端安装ssh2包,然后在需要执行linux命令,运行linux端程序的页面加入以下代码:
$host='*******';//服务器的ip$user='****';//用户名$passwd='******';//密码// 链接远程服务器$connection = ssh2_connect($host, 22); if (!$connection) die('connection to '.$host.':22 failed'); echo'connection OK'; // 获取验证方式并打印$auth_methods = ssh2_auth_none($connection, $user); print_r( $auth_methods.''); if (in_array('password', $auth_methods )) { // 通过password方式登录远程服务器if (ssh2_auth_password($connection, $user, $passwd)) { echo$user.' login OK'; $stream = ssh2_exec($connection, "命令1&&命令2"); // 一条一条地执行linux命令stream_set_blocking($stream, true); // 获取执行pwd后的内容if ($stream === FALSE) die("pwd failed"); echo stream_get_contents($stream).''; } else{ die( $user.' login Failed'); } } ?>
亲测有效。
PHP的登录系统
这里是PHP登录系统的更新版本。你可以在这里查看旧版本。
以下是补充道:
1. 注册字段:
email confirmationpassword confirmationcountryrecaptcha
电子邮件确认和密码确认是可配置的字段。默认情况下显示,但是,如果您希望删除其中一个或两个文件中必须设置constants.php:
define("REPEAT_EMAIL",true);
define("REPEAT_PASSWORD",true);
2. 表字段:
the user ip,number of logins of a user,flag is_adminflag is_blockednew table – Country table
3. dbcontroller类会清除用户输入数据
4. 编辑帐户区域
5. 行政区域-不完整(下一版本)
现在只显示用户列表和显示用户来自何处的世界地图。您可以删除用户并将其设置为管理员。如果没有用户列表,则没有显示地图。也没有显示用户看到面板。
请注意,在演示中,您将无法看到admin部分——由于管理原因:)
6. 新CSS
7. php代码中的其他一些小细节
对于下一个版本,我计划:
添加所有管理功能改善和提高 ….
要使用recaptcha,您需要在这里获得一个公共/私钥。然后您需要在常量.php中定义它们:
define("PUBLICKEY","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
define("PRIVATEKEY","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
为了给在上一个版本的演示中注册的用户使用演示,您需要再次注册(在演示登录系统中),因为我必须为它设置另一个数据库。
希望你喜欢。欢迎任何建议或改进!
更新:这个登录脚本有一个新版本。
这是一个PHP登录系统,基于jpmaster77开发的一个PHP登录系统。
我只关注核心功能,并致力于改进代码的某些部分,我去掉了一些功能,并添加了一些其他功能:
删除:
管理功能活跃用户,活跃用户,禁用用户全局变量链接到其他页面的登录后
所有这些都可以很容易地重新集成,如果你想。我专注于登录和注册部分,省略了内容“inside”。
补充:
PHP 5代替了PHP 4。mysqli扩展发送注册确认链接到电子邮件地址。重置密码功能,不发送密码到电子邮件。相反,一个链接被发送来重置密码。use UTF8支持用于数据库操作的InnoDB事务。使用AJAX注册和表单验证。jQueryCaptcha图像的注册表单,以避免垃圾邮件。
这里是安装登录系统的最重要的设置。
设置在constants.php数据库访问:
define("DB_SERVER", "localhost"); //type mysql server url define("DB_USER", "XXXXXXX"); //type mysql user
define("DB_PASS", "XXXXXXX"); //type mysql password define("DB_NAME", "XXXXXXX"); //type mysql database name
此外,您还必须为邮件发送函数设置以下文件的正确位置:
define("RESETPASSWORDLINK","http:///loginsystem/resetpassword.php");
define("CONFIRMACCOUNTLINK","http:///loginsystem/php/confirm.php");
你在MySQL数据库中唯一需要创建的表格如下:
CREATE TABLE users(
pk_user int unsigned not null auto_increment,
email varchar(120) not null,
flname varchar(100) not null,
password varchar(64) not null,
usr_signup_date timestamp not null default CURRENT_TIMESTAMP,
usr_userid varchar(32),
# for the account confirmation:
usr_confirm_hash varchar(255) not null,
# after confirming its set to 1:
usr_is_confirmed tinyint(1) not null default 0,
# when the user resets password (forgot password):
usr_resetpassword_hash varchar(255) not null,
unique index(email),
primary key(pk_user)
)type=innodb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
我将很快发布一个新版本,因为我目前正在改进一些观点。
今天介绍一下网站里面常见的用户登录功能的实现
用户登录我们先想一想实现思路,先帮常用的代码放在一个include文件,里面放一些链接数据库,常用函数等公用文件。然后常用的用户信息修改。我们看看需要哪些页面
代码文件公用的头部文件和公用的底部文件单独放在一个页面,方便后期维护。然后就是登陆,注册,逻辑处理。
代码是最基础的实现原理。在原理掌握的基础长就可以进行深化,封装成class文件,简化代码和文件,我们先从最基础的实现原理来看看怎么实现。
登陆的界面首先是基本的登陆页面。不含css,后期可以把页面美化一下。
然后看看数据提交到了loginCheck.php页面进行哪些逻辑处理
php逻辑代码处理我们分析代码 显示引用配置文件,我们看看配置文件,也就是最基本的数据库信息,定义一个数组
数据库配置然后在看看mysql.fun.php通过文件名称我们可以知道这是一个操作数据库的代码,我们把一些常用的数据库操作方在这个里面。然后在去调用。
数据库链接操作注意@的用途,感兴趣的朋友去删除这个看看效果。
接着分析代码就是接受用户名和密码,执行查找数据库操作,存在这个记录就跳转到main.php页面,不存在就跳转到login.php页面。这样也就类似实现一个后台登陆管理功能的实现。登陆成功进入后台,登陆失败禁止登陆。原理是不是很简单。有兴趣的朋友快去制作一个登陆功能吧。
登陆后台模板小编收集了一下后台界面模板和登陆界面模板,想加强这方面的也去试试吧。
网站后台管理界面这样就实现了一个最基本的后台管理功能。
//F12中的preserve log记得勾选,(页面刷新不会清空Network)
//打码可以使用打码兔
代码demo
function login_get($url, $httpHeader)
{
$curl = curl_init();//初始化curl模块
curl_setopt($curl, CURLOPT_URL, $url);//登录提交的地址
curl_setopt($curl,CURLOPT_HEADER,1); //显示响应头header信息
curl_setopt($curl, CURLOPT_NOBODY, 1); //不显示显示文档document信息
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出
curl_setopt($curl, CURLOPT_ENCODING, "gzip"); //指定gzip压缩
$Cookie = 'Cookie:name=1;session_id=2;';
$header4 = array(
'Accept:image/webp,image/*,*/*;q=0.8',
'Accept-Encoding:gzip, deflate, sdch, br',
'Accept-Language:zh-CN,zh;q=0.8',
'Connection:keep-alive',
$Cookie,
'Host:网址',
'Referer:网址',
'User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
);
curl_setopt($curl, CURLOPT_HTTPHEADER, $httpHeader); //指定请求头
// curl_setopt($curl, CURLOPT_COOKIEJAR, dirname(__FILE__).'/cookie_xm.cookie');//连接结束后,比如,调用 curl_close 后,保存 cookie 信息在指定的文件中。
// curl_setopt($curl, CURLOPT_COOKIEFILE, $cookieFile); //读取cookie 参数为文件地址
// curl_setopt($curl, CURLOPT_COOKIE, $cookieStr); //读取cookie 参数为字符串
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //SSL 报错时使用
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); //SSL 报错时使用
$rs = curl_exec($curl);//执行cURL
// curl_setopt($curl, CURLINFO_HEADER_OUT, TRUE); //打印请求头
// $request= curl_getinfo($curl); //得到请求头
// file_put_contents("./request.txt", $request['request_header'].PHP_EOL, FILE_APPEND);
//要提交的信息
file_put_contents("./login.txt", $rs.PHP_EOL, FILE_APPEND);
preg_match('/cookiename=(.*);/iU',$rs,$pass_trace);//正则匹配到需要的cookie
// file_put_contents("./rs.txt", $str.PHP_EOL, FILE_APPEND);
curl_close($curl);//关闭cURL资源,并且释放系统资源
return cookiename[0];
}
分离curl header和body
$rs = curl_exec($curl);//执行cURL
//CURLINFO_HEADER_SIZE获取header的size去截取
if (curl_getinfo($curl, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$header = substr($rs, 0, $headerSize);
$body = substr($rs, $headerSize);
}
post方式提交
$post2 = array (
'user' => 'hojun',
'pwd' => '123456#',
);
curl_setopt($curl, CURLOPT_POST, 1);//post方式提交
//http_build_query 使用给出的关联(或下标)数组生成一个经过 URL-encode 的请求字符串
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
今天benny要跟大家说这个其实很简单,就是借用某一个平台的短信api接口实现短信验证,说简单呢,那是因为他的官网:http://www.ucpaas.com上有开发文档,它可以教会一个小白很快的运用它的接口,并开发自己的应用。这个官网还算人性化的,因为你一注册,就给了你10块钱的测试费用来尝试使用它的api,你要知道一条短信0.055元,10块钱给你拿来学习测试已经够多啦!
首先,你进入官网,注册,然后你就点击开发文档:
这里有详细的介绍你怎么用它的东西,我就不在这里bb啦,看完后我们就直接下载一个php的demo文件来试试!!
下载后,你就可以看到一个封装的类Ucpaas.class.php和一个index.php的文件:
上面的注释有详细的解释,要用到的参数啥的,你注册了账号后也就自然有了,多看几遍,有点基础的人几分钟内就可以看得懂的啦!
接着,你就开始阅读官网下面目录的内容:
这里有详细的介绍,我就只是做一个引导吧,具体的大家去阅读哦。
最后,我把这个短信验证功能在我的项目上实现了,你可以看下我的代码截图:
<?php
//载入ucpass类
require('library/Db.class.php');
require_once('library/Ucpaas.class.php');
//初始化必填
$options['accountsid']='******';(这个不能给大家看哦)
$options['token']='******';(这个不能给大家看哦)
//初始化 $options必填
$ucpass = new Ucpaas($options);
//开发者账号信息查询默认为json或xml
header("Content-Type:text/html;charset=utf-8");
//短信验证码(模板短信),默认以65个汉字(同65个英文)为一条(可容纳字数受您应用名称占用字符影响),超过长度短信平台将会自动分割为多条发送。分割后的多条短信将按照具体占用条数计费。
// 验证码短信:同一个手机号1分钟内不能超过2条,24小时内不能超过8条
$appId = "****";(这个不能给大家看哦)
$to=$_POST['to'];
$templateId = "244286";
$string='';
for ($i=0; $i <4 ; $i++) {
$string.=rand(0,9);
}
$param=$string;
$db = new DB();
$sql ="select * from mr_user where username = :username";
$user = $db->row($sql,array('username' =>$to));
//用户名存在
$id=$user['id'];
if ($user){
$password=md5($param);
$update_sql = "update mr_user set password ='$password' where id='$id'";
$result_id = $db->query($update_sql);
if ($result_id){
$data=$ucpass->templateSMS($appId,$to,$templateId,$param);
$re='';
$arr = json_decode($data,true);
foreach ($arr as $key => $value) {
if ($key=='resp') {
foreach ($value as $key2 => $value2) {
if ($key2=='respCode') {
$re=$value2;
}
}
}
}
if ($re=='000000') {
echo 1;//短信已发送!
}elseif ($re=='105147') {
echo 3;//短信发送太频繁
}else{
echo 2;//号码输入有误
}
exit(0);
}
else{
echo 0;//短信发送出错!
}
}else {
$data=$ucpass->templateSMS($appId,$to,$templateId,$param);
$re='';
$arr = json_decode($data,true);
foreach ($arr as $key => $value) {
if ($key=='resp') {
foreach ($value as $key2 => $value2) {
if ($key2=='respCode') {
$re=$value2;
}
}
}
}
if ($re=='000000') {
$addtime = time();
$insert_sql = "insert into mr_user(username,password,addtime) value(:username,:password,$addtime)";
$result_id = $db->query($insert_sql,array('username' =>$to,'password'=>md5($param)));
if ($result_id){
echo 1;//短信已发送!
}else{
echo 0;//短信发送出错!
}
}elseif($re='105147'){
echo 3;//短信发送太频繁
}else{
echo 2;//号码输入有误
}
}
图|来源截图
不当你的世界 只作你的肩膀
○
Benny
○
技术帖