需要用到的网站
sha加密:https://www.wetools.com/sha
时间戳:https://tool.lu/timestamp/
代码实现
客户端加密:http://domain/?id=id&appid=appid&appsecret=appsecret&ts=ts
请求鉴权:http://domain/?id=id&appid=appid&token=token&ts=ts
<? interface CredentialStorage{ public function getAppsecretByAppid(String $appid); } class IniCredentialStorage implements CredentialStorage{ public function getAppsecretByAppid(String $appid){ $ini_path = str_replace("\\",'/',__DIR__)."/config.ini"; if(!is_file($ini_path)){ throw new \Exception("没有找到配置文件",-1); }else{ $ini_data = parse_ini_file($ini_path,true); if(isset($ini_data['auth'][$appid])){ return $ini_data['auth'][$appid]; }else{ throw new \Exception("没有找到匹配的appid",-2); } } } } class AuthToken{ const DEFAULT_EXPIRED_TIME_INTERVAL = 1*60;//有效期60s private $token; private $createTime; private $expiredTimeInterval = self::DEFAULT_EXPIRED_TIME_INTERVAL; public function __construct($token, $createTime){ $this->token = $token; $this->createTime = $createTime; } public function generate($originalUrl, $appId, $password, $timestamp){ $token = sha1($originalUrl.'&appid='.$appId.'&appsecret='.$password.'&ts='.$timestamp); $this->token = $token; } public function getToken(){ return $this->token; } public function isExpired(){ if($this->createTime + self::DEFAULT_EXPIRED_TIME_INTERVAL < time()){ return true; } return false; } public function match($token){ if($token === $this->token){ return true; } return false; } } class ApiRequest{ private static $baseUrl; private static $token; private static $appid; private static $timestamp; public function __construct(){ } public static function createFromUrl($url){ preg_match('/appid=([\w]+)&token=([\w]+)&ts=([\d]+)/', $url, $matches); self::$appid = $matches[1]; self::$token = $matches[2]; self::$timestamp = $matches[3]; self::$baseUrl = str_replace("&","",substr($url,0,strlen($url)-strlen($matches[0]))); return new self; } public function getBaseUrl(){ return self::$baseUrl; } public function getToken(){ return self::$token; } public function getAppid(){ return self::$appid; } public function getTimestamp(){ return self::$timestamp; } } interface ApiAuthenticator { public function auth(String $url); public function auth_url(ApiRequest $apiRequest); } class DefaultApiAuthenticatorImpl implements ApiAuthenticator { private $credentialStorage; public function __construct(CredentialStorage $credentialStorage) { $this->credentialStorage = $credentialStorage; } public function auth(String $url) { $apiRequest = ApiRequest::createFromUrl($url); return self::auth_url($apiRequest); } public function auth_url(ApiRequest $apiRequest) { $appId = $apiRequest->getAppId(); $token = $apiRequest->getToken(); $timestamp = $apiRequest->getTimestamp(); $originalUrl = $apiRequest->getBaseUrl(); $clientAuthToken = new AuthToken($token, $timestamp); if ($clientAuthToken->isExpired()) { throw new \Exception("Token is expired.",-3); } $password = $this->credentialStorage->getAppsecretByAppid($appId); $clientAuthToken->generate($originalUrl, $appId, $password, $timestamp); if (!$clientAuthToken->match($token)) { throw new \Exception("Token verfication failed.",-4); } return true; } } $domain = $_SERVER['REQUEST_SCHEME']."://".$_SERVER['HTTP_HOST']; $uri = $_SERVER['REQUEST_URI']; $api_auth_impl = new DefaultApiAuthenticatorImpl(new IniCredentialStorage()); try { $ret = $api_auth_impl->auth($domain.$uri); } catch (Exception $e) { echo $e->getMessage()." ".$e->getCode(); }
鉴权的其它实现
OAuth 2.0 + 网关(如Zuul)+ 认证中心 + AOP实现。还可以通过业务模型规避风险: 1. 充值类业务,就算对方篡改接口,最终结果可以通调用证金融机构的接口验证是否有效,不会给公司带来损失。 2. 如果安全等级非常高,比如提现、转账可以通过发送手机短信,确保是本人操作。 3. 如果是商品信息查询类接口,防止第三方爬取数据,可以在调用一定次数后加入人机验证(输入图片识别码、拼图)。 4. 根据IP限制访问次数。 5. 服务器间调用可以绑定mac地址、IP。 6. 服务器、客户端通过架设私有VPN进行通信,将安全问题转移到VPN上,降低业务复杂度的同时还可以避免加解密带来的性能损耗,提升性能。 7. 调用接口时通过付费方式(如实名认证、银行四要素验证这些调用一次都是要收费的),防止恶意调用。 8. 通过独立加密硬件(如U盾)+ 独立密码验证器(Google验证器)+ 语音识别 + 面部识别(刷脸支付) + 指纹 + 多人同时输入动态秘钥(核打击时发射程序)。 9. 安全性会降低系统性能适可而止。