设计思路: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