設計思路:1、前后端商定統一的加密規則;2、后端配置文件保存固定的驗證字符串;3、對前端傳的加密sign進行合法性驗證、時效驗證、唯一性驗證;
代碼如下:
1、驗證前端傳過來的sign(拋出異常的接口是我自己框架封裝的接口,沒封裝可以改成Exception)
<?php /** * Created by PhpStorm. * User: hjx(2896751917@qq.com) * Date: 2019/2/21 */ namespace app\api\controller; use app\common\lib\exception\ApiException; use app\common\lib\extend\Aes; use think\Cache; use think\Controller; use think\Request; class Common extends Controller { protected $apiToken = null; public function __construct(Request $request = null) { parent::__construct($request); $this->verifyToken(); } /** * 訪問API時進行sign驗證 * @return bool * @throws ApiException */ public function verifyToken() { $data = input('param.'); $validate = validate('Common'); if(!$validate->check($data)) { throw new ApiException($validate->getError(), 400); } $str = (new Aes())->decrypt($data['sign']); if(!$str) { throw new ApiException('sign不合法', 401); } list($t1,$t2) = explode('&',$str); //sign失效時間 if(time() - $t1 > 600) { throw new ApiException('sign已過期', 401); } //驗證規則 if($t2 != config('api.CorpId')) { throw new ApiException('sign不合法', 401); } //驗證sign唯一性 if(Cache::get($data['sign'])) { throw new ApiException('sign已使用過', 401); } Cache::set($data['sign'],1,3600); return true; } }
2、各個控制器都繼承上面的Common控制器即可
3、后台加密規則
<?php /** * Created by PhpStorm. * User: hjx * Date: 2019/3/12 * Time: 10:41 */ namespace app\api\controller; use app\common\lib\extend\Aes; class Test { /** * token創建規則,以后前端得按照這個規則進行 * @return \app\common\lib\extend\HexString */ public function createToken() { $str = time().'&'.config('api.CorpId'); return (new Aes())->encrypt($str); } }
后台加密只是示例的加密規則,可以給前端按照這種加密方式進行加密得到sign