设计思路:1、前后端商定统一的加密规则;2、后端配置文件保存固定的验证字符串;3、对前端传的加密sign进行合法性验证、时效验证、唯一性验证;
代码如下:
1、验证前端传过来的sign(抛出异常的接口是我自己框架封装的接口,没封装可以改成Exception)
/**
* 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、后台加密规则
/**
* 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