我们给它叫做“老赵API系统”。

首先,我们要做的这个API系统是私有的,不开源的,不分发给其它人一起用(当然你非要大力推广,也随便你)。

其次,我故意遗漏了一个小小的点子,这个点子我自己用,我也是怕我这个办法透露后会有安全问题。

isapiphp若何用PHP写一个比拟平安的API体系实现 Python

就当是抛砖引玉吧。

先说要把稳的几点:

0、不要利用默认首页

1、不该用SESSION和COOKIE

2、每次访问都须要验证用户名密码

3、任何单个文件都不许可能正常运行

4、任何单个文件都不许可能单独实现任何功能

5、未验证成功身份时不输出任何缺点提示

相信很多高人一看这几条就会知道我要怎么做。
也会有一部分人会嗤之以鼻说太初级。

管他呢,反正这是我自己摸索出来的,便是黑客黑我也只能在操作系统方面下手,在我这套系统里他永久不可能有成功的访问要求。

下面详细说:

0、不要利用默认首页。

如果你的环境里首页设置了很多,比如index.php,index.html,default.html,default.php之类的,那么你API的接口文件一定不能用这些,比如你可以用iLaoZhao_XX_api.php,这谁猜得到?

1、不该用SESSION和COOKIE。

COOKIE是用明文存在于用户真个,很随意马虎查看和修正,这个大家都清楚。
而PHP的SESSION也依赖于COOKIE来存储一个SESSION_ID。
并且我们的API要每次访问就返回一次数据,很多访问方法并不会存储COOKIE,这会导致SESSION失落效。

2、每次访问都验证用户名密码。

现在盛行那个啥叫Token的办法,我

3、任何单个文件都不许可能正常运行。

资源文件夹不能有任何可实行文件。
并且只管即便多分几个文件,所有的文件相互依赖,并且把它们相互组织起来的文件又是另一个单独文件,这样即便别人知道了我们的文件路径和文件名,当访问这个文件时,也无法正常运行。

4、任何单个文件都不许可能单独实现任何功能。

某个文件要实现功能,必须依赖其它文件内的函数或类,并且当前文件不能知道这些函数和类详细在哪个文件里实现的。
这样即便这个文件的源代码透露,对方也不知道里面的依赖关系,不会连累到其它文件。

5、未验证成功身份时不输出任何缺点提示。

在用户名密码出错时,系统不要输出任何有用的信息,或者输出一个假的404信息,这样别人在试探我们的系统时,根本不知道是哪一步出错了,而我们的客户端可以根据里面的暗语来判断状态。

我做一个小例子来解释一下,这个小例子只是抛砖引玉,并不是我终极的代码样子。

文件树构造:

老赵API文件树构造

根目录下只有一个文件夹,全体API系统都通过一个接口文件"DaYeLaiWanA.php"来调用。

怎么样,不知道文件构造的人根本猜不对你有哪些文件,也就不能访问任何文件。

下面的代码没有利用太前辈的语法,比如类和工具啊命名空间啊啥的,新版本PHP添了好多特性,但我比较方向于不去利用它们,我要只管即便的让代码对环境没有哀求,在尽可能多的版本环境下都能运行。

毕竟我们要的是安全,而不是让所有人能读懂我们的代码。

我们要尽可能的不该用教科书上的通用的写法,尽可能搞一套自己的写法。

下面是DaYeLaiWanA.php的代码:

<?php//接口文件,单独调用这个文件没任何浸染,参数必须得对,差一个字母这个文件都运行不出个毛线来。
//而参数是你自己定的,可随意加密修正。
//当然你还可以把这个路径也放到变量里,然后藏起来。
include "./iLaoZhao_funs/postget.php"; //没有依赖,但也不实现任何详细功能include "./iLaoZhao_funs/login.php"; //依赖pdo,dbfuns,postget和接口文件include "./iLaoZhao_funs/curl.php"; //没有依赖,但也不实现任何详细功能include "./iLaoZhao_funs/dbfuns.php"; //依赖pdo和接口文件//上面这些文件里涉及到安全的功能都有依赖,并且他们不知道要用的函数在哪//全靠这个接口文件把它们组合到一起//并且上面的函数里也会用到接口文件的函数(便是下面那个)//这些成分缺一不可,只能由接口文件来整合他们//上面这些文件和其它的API文件,都无法单独运行。
不是缺这便是缺那。
//下面这俩函数是故意没单独放文件里的,为的便是其它文件短缺这个接口文件时在调用这个函数时会出错。
function output2Die($msg, $code = -1, $data = ''){ $dieMsg['code'] = $code; $dieMsg['msg'] = $msg;$dieMsg['data'] = $data; echo json_encode($dieMsg); die();}function isPhone($phonenumber){ return preg_match("/^1[3-9]\d{9}$/", $phonenumber);}$area = POST("area");//要利用的API种类$class = POST("class");//要利用的API小分类$fun = POST("fun");//要利用的API功能//清理POSTunset($_POST['area']);unset($_POST['class']);unset($_POST['fun']);if ($class !== FALSE && $fun !== FALSE){ if ($area == false){$area = "public";} //天生API文件全名,这里没加密,你可以自己变动这里。
$incFile = dirname(__FILE__)."/{$area}/{$class}/{$fun}.php"; if (file_exists($incFile)){ //检讨API文件是否存在,实在不检讨也行。
include "./config/pdodb.php"; //创建数据库连接,依赖接口文件 include $incFile;//将单独的API文件导入进来 }else{//我由于调试的缘故原由,显示了缺点信息,哀求高的可以去掉。
output2Die("无效的要求", -1); }}else{output2Die("无效的要求", -2);}

文件我写了注释,方便大家看,实际在利用时不能有这些注释,这些注释只能方便别人破解我们的系统,并且这个接口文件尽可能进行代码稠浊加密。

然后是一个获得当前用户信息的小例子API,这个API文件存在了/iLaoZhao_api/public/login/usrMsg.php里面。
在调用时大概URL是这样:

https://你的域名/iLaoZhao_api/DaYeLaiWanA.php

POST数据为:{key:"用户名密码韶光加密字符串运算后的结果",class:"login",fun:"usrMsg",userName:"该用户的用户名"}

API代码内容usrMsg.php为:

<?php//示例文件,得到当前用户的所有信息//文件依赖:接口文件、数据库连接文件、dbfuns文件、login文件//单独访问这个文件根本不能运行//依赖关系完备靠接口文件处理//这个API读取post参数中的userNamecheckUserNamePassWord(); //检讨用户名密码,不对真接就终止运行了,对了的话就可以运行下面的代码$dbArr['userName'] = POST("userName");if($dbArr['userName'] !== false){ //这一步没必要,能验证过上面那个函数,这个参数肯定存在,但我便是写了,便是玩儿//一定要用PDO的绑定功能访问数据库,这种办法能避免SQL注入。
$sql = "select from tb_users where users_userName = :userName";$rec = db_query($sql,$dbArr);if($rec['count'] > 0){output2Die("成功。
",1,$rec);}else{output2Die("找不到该用户。
",-1); //哀求高的,不要输出错误信息。
}}output2Die("失落败",-2); //哀求高的,不要输出错误信息。

这里面的checkUserNamePassWord()函数(在iLaoZhao_funs文件夹内的login.php文件里)也比较关键:

<?php/ 判断用户名密码的函数 此函数不许可返回东西 调用的时候直接调用 用户正常自然没反应 用户不正常,这个函数直接结束程序运行。
/function checkUserNamePassWord(){$keyStr = "这里是加密字符串,这个串只有你自己知道是什么。
";$key = POST("key"); //这个key是客户端把用户名密码韶光加密字符串运算后的结果//用当前日期当第二密钥,这个浸染是每天的密钥都不一样。
//即便被拦截了,也算不出规律来,当然源码透露了就弗成了。
//不能太精确,由于客户端与做事器真个韶光不可能完备一样。
$keyStr_Today = date('Ymd',time());//访问数据库,一定要用PDO的这个参数办法。
//这个办法在代入数据与直接写在SQL语句里不一样。
//sql注入在这种利用办法下完备不会生效。
$sqlPar['username'] = POST("userName"); //这个没加密的必要,这个在输入框里就能看到,而且也会在很多地方显示。
if($sqlPar['username'] === false || $key === false){//造孽调用}//不要在sql里直接比对用户名密码//而且传过来的数据也没有密码//要取出该用户的记录,然后打算后与传过来的加密身份信息比拟$sql = "select from tb_users where userName=:username"; //你可以在这limit 1$rec = db_query($sql, $sqlPar);if($rec['count'] > 0){$keyInDB = md5(md5($keyStr).md5($rec['rows'][0]['userName']).md5($keyStr_Today).md5($rec['rows'][0]['passWord']));//上面这句是加密办法,把加密字符串、用户名、当前日期、密码的MD5连接起来并再打算一次MD5//当然你还可以再加点别的东西,比如字符串反转,以及其它变量之类的。
//上面这句打算出来的和$key中的一样时,解释密码是对的。
if($key == $keyInDB){//用户名密码对//此时我们啥也不做//或者你想设置某些变量也行}else{//否则die(); //结束程序运行,}}}

代码里都有注释,该当能看清楚。
而且还有其它的自定义函数我就不放代码了。

这样我们在扩充API时只须要在对应路径下写PHP代码文件就行,而且很多函数可以直策应用,不用include任何文件。

而且这个别系内所有的文件在单独访问时都会出错(可以设置PHP不显示缺点信息),而接口文件在参数禁绝确的情形下也不会有什么详细运行结果。

也没有默认的首页文档可以访问。

文件路径和文件名都没规律,在网上都查不到参考。

那么想黑掉这套API只有两个办法:

0、黑掉做事器操作系统,再从文件系统入手。

1、破解客户端代码或者拦截访问数据,找到访问规律。

这两点暂时无能为力办理。

边写文档边写代码,头有点乱,可能有遗漏的东西,不知道大家能不能看懂。

此API系统还有很多地方可以进一步加密处理,但我个人觉得没必要了。
已经够可以了。

此代码没有利用太前辈的语法,比如类啊命名空间啊啥的,新版本PHP添了好多特性,但我比较方向于不去利用它们,我要只管即便的让代码对环境没有哀求,在尽可能多的版本环境下都能运行。

毕竟我们要的是安全,而不是让所有人能读懂我们的代码。

有啥忘了的往后再补充吧。