摘要:一,為項(xiàng)目搭建數(shù)據(jù)庫設(shè)計(jì)數(shù)據(jù)庫的小技巧一個(gè)對(duì)象,一張表一張表,一個(gè)主鍵表名用數(shù)據(jù)庫名做前綴字段名用表名做前綴前綴后面加縮寫容易看懂的前提下數(shù)據(jù)表的關(guān)系處理二,為項(xiàng)目寫接口文檔用戶登錄舉例判斷數(shù)據(jù)庫中是否有此用戶參數(shù)必選類型說明時(shí)間戳用于確定
一,為api項(xiàng)目搭建數(shù)據(jù)庫
一個(gè)對(duì)象,一張表
一張表,一個(gè)主鍵
表名用 數(shù)據(jù)庫名 做前綴
字段名用 表名 做前綴
前綴后面加 縮寫 (容易看懂的前提下)
數(shù)據(jù)表的關(guān)系處理
二,為api項(xiàng)目寫接口文檔用戶登錄舉例
# 判斷數(shù)據(jù)庫中是否有此用戶
postwww.test.com/apiapi.test.com
參數(shù) | 必選 | 類型 | 說明 |
---|---|---|---|
time | true | int | 時(shí)間戳 (用于確定接口的訪問時(shí)間) |
token | true | string | 確定訪問者身份 (MD5(USER_MD5(time)_USER)) |
username | true | string | 只接受郵箱 |
password | true | string | 用戶密碼 |
{ "ret": 200, // 返回結(jié)果狀態(tài)。200:接口正常請(qǐng)求并返回/40*:服務(wù)端的數(shù)據(jù)有誤/500:服務(wù)器運(yùn)行錯(cuò)誤 "data": { "user_id": "27", // 用戶id "user_tag": "1" // 用戶身份 }, "msg": "" // 401:用戶名不存在!/402:手機(jī)號(hào)不存在!/403:密碼不正確! }三,配置URL
· api.test.com ===> www.test.com/index.php/api
打開 httpd-vhosts.conf 添加 ServerAlias api.test.com
配置 host 文件 127.0.0.1 api.test.com
新建User.php文件,路徑 G:tp5/application/api/controller/User.php
"; echo $id; } }
修改 config.php (開啟路由)
// 是否開啟路由
"url_route_on" => true,
// 域名部署
"url_domain_deploy" => true,
配置路由規(guī)則 route.php
www.test.com/index.php/api Route::domain("api","api");四,接口安全
接口被大規(guī)模調(diào)用消耗系統(tǒng)資源,影響系統(tǒng)的正常訪問,甚至系統(tǒng)癱瘓
解決方案: 獲取 timestamp (時(shí)間戳), 設(shè)置接口失效時(shí)間
接口數(shù)據(jù)被黑客篡改(偽造請(qǐng)求)
解決方案: 對(duì)參數(shù)加密, 生成 token , 判斷 token 是否正確
數(shù)據(jù)被黑客截取
解決方案: 使用 https , 用證書對(duì)數(shù)據(jù)進(jìn)行加密, 即使數(shù)據(jù)被截取, 對(duì)黑客也沒有意義
time
時(shí)間戳, 用于判斷請(qǐng)求是否超時(shí), 設(shè)置為30秒
token
其他參數(shù)加密而來, 保證數(shù)據(jù)不被篡改
敏感信息加密傳輸
接收加密過的用戶密碼, 用戶密碼永不返回五,開發(fā)前準(zhǔn)備工作(參數(shù)過濾)
最好使用 https, 所有信息都會(huì)被加密
使用 common.php 統(tǒng)一處理參數(shù)過濾 G:tp5/application/api/controller/Common.php
array(......); protected function _initialize() { parent::_initialize(); $this->request = Request::instance(); $this->check_time($this->request->only(["time"])); $this->check_token($this->request->param()); $this->params=$this->check_params($this->request->except(["time","token"])); }
自定義返回信息函數(shù) G:tp5/application/api/controller/Common.php
/** * api 數(shù)據(jù)返回 * @param [int] $code [結(jié)果碼 200:正常/4**數(shù)據(jù)問題/5**服務(wù)器問題] * @param [string] $msg [接口要返回的提示信息] * @param [array] $data [接口要返回的數(shù)據(jù)] * @return [string] [最終的json數(shù)據(jù)] */ public function return_msg($code, $msg = "", $data = []) { /*********** 組合數(shù)據(jù) ***********/ $return_data["code"] = $code; $return_data["msg"] = $msg; $return_data["data"] = $data; /*********** 返回信息并終止腳本 ***********/ echo json_encode($return_data);die; }
驗(yàn)證 time G:tp5/application/api/controller/Common.php
/** * 驗(yàn)證請(qǐng)求是否超時(shí) * @param [array] $arr [包含時(shí)間戳的參數(shù)數(shù)組] * @return [json] [檢測(cè)結(jié)果] */ public function check_time($arr) { if (!isset($arr["time"]) || intval($arr["time"]) <= 1) { $this->return_msg(400, "時(shí)間戳不正確!"); } if (time() - intval($arr["time"]) > 60) { $this->return_msg(400, "請(qǐng)求超時(shí)!"); } }
驗(yàn)證token G:tp5/application/api/controller/Common.php
/** * 驗(yàn)證token(防止篡改數(shù)據(jù)) * @param [array] $arr [全部請(qǐng)求參數(shù)] * @return [json] [token驗(yàn)證結(jié)果] */ public function check_token($arr) { /*********** api傳過來的token ***********/ if (!isset($arr["token"]) || empty($arr["token"])) { $this->return_msg(400, "token不能為空!"); } $app_token = $arr["token"]; // api傳過來的token /*********** 服務(wù)器端生成token ***********/ unset($arr["token"]); $service_token = ""; foreach ($arr as $key => $value) { $service_token .= md5($value); } $service_token = md5("api_" . $service_token . "_api"); // 服務(wù)器端即時(shí)生成的token /*********** 對(duì)比token,返回結(jié)果 ***********/ if ($app_token !== $service_token) { $this->return_msg(400, "token值不正確!"); } }
為每個(gè)接口配置驗(yàn)證規(guī)則 G:tp5/application/api/controller/Common.php 如
protected $rules = array( "User" => array( "login" => array( "user_name" => ["require", "chsDash", "max" => 20], "user_pwd" => "require|length:32", ), ), );
驗(yàn)證參數(shù) G:tp5/application/api/controller/Common.php
/** * 驗(yàn)證參數(shù) 參數(shù)過濾 * @param [array] $arr [除time和token外的所有參數(shù)] * @return [return] [合格的參數(shù)數(shù)組] */ public function check_params($arr) { /*********** 獲取參數(shù)的驗(yàn)證規(guī)則 ***********/ $rule = $this->rules[$this->request->controller()][$this->request->action()]; /*********** 驗(yàn)證參數(shù)并返回錯(cuò)誤 ***********/ $this->validater = new Validate($rule); if (!$this->validater->check($arr)) { $this->return_msg(400, $this->validater->getError()); } /*********** 如果正常,通過驗(yàn)證 ***********/ return $arr; }五,獲取驗(yàn)證碼
驗(yàn)證碼原理
生成及發(fā)送
點(diǎn)擊獲取驗(yàn)證碼
發(fā)送郵箱號(hào)到后臺(tái)
后臺(tái)生成郵箱驗(yàn)證碼
用session保存驗(yàn)證碼及郵箱
發(fā)送郵件
驗(yàn)證
獲取用戶輸入的驗(yàn)證碼及郵箱
取出session保存的內(nèi)容
對(duì)比驗(yàn)證
返回信息, 結(jié)束
配置路由 G:tp5/application/route.php
注意: get方式?jīng)]有參數(shù)名, 所以要注意參數(shù)的順序, 對(duì)號(hào)入座.
// 獲取驗(yàn)證碼 Route::get("code/:time/:token/:username/:is_exist","code/get_code");
參數(shù)過濾 G:tp5/application/api/controller/Common.php
在common.php里簡單過濾, 具體驗(yàn)證放在code.php里
"Code" => array( "get_code" => array( "username" => "require", "is_exist" => "require|number|length:1", ), ),
檢測(cè)用戶名 G:tp5/application/api/controller/Code.php
namespace appapicontroller; use phpmailerphpmailer; use submailmessagexsend; class Code extends Common { public function get_code() { $username = $this->params["username"]; $exist = $this->params["is_exist"]; $username_type = $this->check_username($username); // 檢查用戶名, 決定用下面哪那個(gè)函數(shù) switch ($username_type) { case "phone": $this->get_code_by_username($username, "phone", $exist); // 通過手機(jī)獲取驗(yàn)證碼 break; case "email": $this->get_code_by_username($username, "email", $exist); // 通過郵箱獲取驗(yàn)證碼 break; } } }
在 Common.php中寫一個(gè)判斷用戶名類型的函數(shù)
public function check_username($username) { /*********** 判斷是否為郵箱 ***********/ $is_email = Validate::is($username, "email") ? 1 : 0; /*********** 判斷是否為手機(jī) ***********/ $is_phone = preg_match("/^1[34578]d{9}$/", $username) ? 4 : 2; /*********** 最終結(jié)果 ***********/ $flag = $is_email + $is_phone; switch ($flag) { /*********** not phone not email ***********/ case 2: $this->return_msg(400, "郵箱或手機(jī)號(hào)不正確!"); break; /*********** is email not phone ***********/ case 3: return "email"; break; /*********** is phone not email ***********/ case 4: return "phone"; break; } }
通過用戶名(手機(jī)/郵箱)獲取驗(yàn)證碼 G:tp5/application/api/controller/Code.php
public function get_code_by_username($username, $type, $exist) { if ($type == "phone") { $type_name = "手機(jī)"; } else { $type_name = "郵箱"; } /*********** 檢測(cè)手機(jī)號(hào)/郵箱是否存在 ***********/ $this->check_exist($username, $type, $exist); /*********** 檢查驗(yàn)證碼請(qǐng)求頻率 30秒一次 ***********/ if (session("?" . $username . "_last_send_time")) { if (time() - session($username . "_last_send_time") < 30) { $this->return_msg(400, $type_name . "驗(yàn)證碼,每30秒只能發(fā)送一次!"); } } /*********** 生成驗(yàn)證碼 ***********/ $code = $this->make_code(6); /*********** 使用session存儲(chǔ)驗(yàn)證碼, 方便比對(duì), md5加密 ***********/ $md5_code = md5($username . "_" . md5($code)); session($username . "_code", $md5_code); /*********** 使用session存儲(chǔ)驗(yàn)證碼的發(fā)送時(shí)間 ***********/ session($username . "_last_send_time", time()); /*********** 發(fā)送驗(yàn)證碼 ***********/ if ($type == "phone") { $this->send_code_to_phone($username, $code); } else { $this->send_code_to_email($username, $code); } }
判斷用戶名(手機(jī)/郵箱)在數(shù)據(jù)庫中是否應(yīng)該存在(因?yàn)橐謨煞N情況1,注冊(cè) 2,修改)
當(dāng)我們注冊(cè)的時(shí)候數(shù)據(jù)庫里不能有,當(dāng)我們修改的時(shí)候數(shù)據(jù)庫里必須有
G:tp5/application/api/controller/Common.php
public function check_exist($value, $type, $exist) { $type_num = $type == "phone" ? 2 : 4; $flag = $type_num + $exist; $phone_res = db("user")->where("user_phone", $value)->find(); $email_res = db("user")->where("user_email", $value)->find(); switch ($flag) { /*********** 2+0 phone need no exist ***********/ case 2: if ($phone_res) { $this->return_msg(400, "此手機(jī)號(hào)已被占用!"); } break; /*********** 2+1 phone need exist ***********/ case 3: if (!$phone_res) { $this->return_msg(400, "此手機(jī)號(hào)不存在!"); } break; /*********** 4+0 email need no exist ***********/ case 4: if ($email_res) { $this->return_msg(400, "此郵箱已被占用!"); } break; /*********** 4+1 email need exist ***********/ case 5: if (!$email_res) { $this->return_msg(400, "此郵箱不存在!"); } break; } }
在 Code.php 中生成驗(yàn)證碼
public function make_code($num) { $max = pow(10, $num) - 1; $min = pow(10, $num - 1); return rand($min, $max); }
只介紹郵箱發(fā)送驗(yàn)證碼
開啟郵箱smtp
php 開啟php_openssl
G:tp5/application/api/controller/Code.php
public function send_code_to_email($email, $code) { $toemail = $email; $mail = new PHPMailer(); $mail->isSMTP(); $mail->CharSet = "utf8"; // 設(shè)置字符集 $mail->Host = "smtp.qq.com"; // smtp服務(wù)器 $mail->SMTPAuth = true; $mail->Username = "[email protected]"; $mail->Password = "asd1151sad51dsa"; // 自己設(shè)置的smtp密碼, 與登錄密碼無關(guān) $mail->SMTPSecure = "ssl"; $mail->Port = 465; $mail->setFrom("[email protected]", "接口測(cè)試"); $mail->addAddress($toemail, "test"); $mail->addReplyTo("[email protected]", "lee"); $mail->Subject = "您有新的驗(yàn)證碼!"; // 郵件標(biāo)題 $mail->Body = "這是一個(gè)測(cè)試郵件,您的驗(yàn)證碼是$code,驗(yàn)證碼的有效期為1分鐘,本郵件請(qǐng)勿回復(fù)!"; // 郵件內(nèi)容 if (!$mail->send()) { $this->return_msg(400, $mail->ErrorInfo); } else { $this->return_msg(200, "驗(yàn)證碼已經(jīng)發(fā)送成功,請(qǐng)注意查收!"); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/26035.html
摘要:分享一個(gè)版本的查詢天氣接口。那就用聚合數(shù)據(jù)的天氣接口吧,也是免費(fèi)的,不過聚合數(shù)據(jù)的接口申請(qǐng)相對(duì)繁瑣。注冊(cè)一個(gè)聚合數(shù)據(jù)的賬號(hào)實(shí)名認(rèn)證你的賬號(hào)申請(qǐng)你需要的接口申請(qǐng)驗(yàn)證你的接口申請(qǐng)地址雖然是繁瑣了很多,不過返回的信息確是非常的豐富。 分享一個(gè)php版本的查詢天氣接口。免費(fèi)查詢天氣的接口有很多,比如百度的apistore的天氣api接口,我本來想采用這個(gè)接口的,可惜今天百度apistore死活...
摘要:的關(guān)聯(lián)應(yīng)用參考的多對(duì)多關(guān)聯(lián)文檔,給大家簡單介紹一下我在項(xiàng)目應(yīng)用中的實(shí)現(xiàn)。數(shù)據(jù)表根據(jù)繪制的圖我們可以確定,訂單票據(jù)的數(shù)據(jù)表實(shí)現(xiàn)需要三張表,訂單表是數(shù)據(jù)庫關(guān)鍵字因此不能作為表名,票據(jù)表,中間表。 TP5的關(guān)聯(lián)應(yīng)用 參考TP5的多對(duì)多關(guān)聯(lián)文檔,給大家簡單介紹一下我在項(xiàng)目應(yīng)用中的實(shí)現(xiàn)。 ER圖講解多對(duì)多關(guān)系 showImg(https://segmentfault.com/img/bV7to2...
摘要:因公司業(yè)務(wù)需要需要給客戶接入支付寶支付自己以前只做過網(wǎng)頁版支付寶支付。添加功能完后我的應(yīng)用列表就會(huì)顯示添加的應(yīng)用,即支付寶支付。最后別忘了在異步方法返回一個(gè),否則支付寶會(huì)以為沒支付成功,小時(shí)內(nèi)每個(gè)幾分鐘就調(diào)一次異步接口。 因公司業(yè)務(wù)需要,需要給客戶接入支付寶支付,自己以前只做過網(wǎng)頁版支付寶支付。折騰了3天,踩了很多坑,終于搞定了,現(xiàn)在記錄一下,分享給大家.一、首先必須通知客戶先申請(qǐng)支付...
摘要:因公司業(yè)務(wù)需要需要給客戶接入支付寶支付自己以前只做過網(wǎng)頁版支付寶支付。添加功能完后我的應(yīng)用列表就會(huì)顯示添加的應(yīng)用,即支付寶支付。最后別忘了在異步方法返回一個(gè),否則支付寶會(huì)以為沒支付成功,小時(shí)內(nèi)每個(gè)幾分鐘就調(diào)一次異步接口。 因公司業(yè)務(wù)需要,需要給客戶接入支付寶支付,自己以前只做過網(wǎng)頁版支付寶支付。折騰了3天,踩了很多坑,終于搞定了,現(xiàn)在記錄一下,分享給大家.一、首先必須通知客戶先申請(qǐng)支付...
摘要:現(xiàn)在我就用框架來進(jìn)行實(shí)戰(zhàn)下在實(shí)際業(yè)務(wù)中是如何優(yōu)雅的使用異常的場(chǎng)景描述選擇一個(gè)比較簡單的業(yè)務(wù)場(chǎng)景,以登錄模塊為例,用戶在移動(dòng)端進(jìn)行登錄時(shí),需要進(jìn)行登錄,注冊(cè),忘記密碼,獲取手機(jī)驗(yàn)證碼等接口。 前言 剛開始接觸PHP的時(shí)候沒有意識(shí)到異常的重要性,有時(shí)候出問題很難精確的找到問題點(diǎn),正確的處理異常也是一門學(xué)問 異常的類別 PHP7異常做了很多變動(dòng),異常類 Exception 和錯(cuò)誤類 Erro...
閱讀 766·2021-09-28 09:35
閱讀 2598·2019-08-29 11:25
閱讀 2161·2019-08-23 18:36
閱讀 1861·2019-08-23 16:31
閱讀 2076·2019-08-23 14:50
閱讀 3127·2019-08-23 13:55
閱讀 3297·2019-08-23 12:49
閱讀 2088·2019-08-23 11:46