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