|
<?php
namespace api\components;
use common\helper\CaptchaHelper;
use phpDocumentor\Reflection\Types\True_;
use services\CommonService;
use services\users\UserService;
use share\jobs\users\CommonJobs;
use share\models\Users;
use yii;
use yii\web\Controller;
use yii\web\Response;
use yii\web\HttpException;
use yii\base\UserException;
class ApiController extends Controller
{
private $debug = HT_DEBUG;
protected $needLogin = true;
protected $needSign = true;
protected $userId = 0;
protected $_user;
protected $params;
protected $_post;
protected $format = Response::FORMAT_JSON;
protected $_data = [];
const AUTO_CHECK = false;
protected $_no_encode = ['config', 'error', 'wechat'];
// HUATANG_API_SECRET_NEWYEAR
protected $sign_secret = 'HUATANG_API_SECRET';
/**
* @var array $_no_catch 不拦截的action列表
* key 为module/controller
* value 为,号拼接的action列表, 如果为空,则controller不需要拦截
*/
protected $_no_catch = [
'user' . D_S . 'attention' => 'news,more,list,scope',
];
public $enableCsrfValidation = false;
public function init()
{
parent::init();
// \Yii::$app->cache->flush();
Yii::$app->getResponse()->on(Response::EVENT_BEFORE_SEND, [$this, 'beforeSend']);
}
/**
* 尝试次数限制
* 通过ip进行限制
* @param $params
* @param $funcName
* @param int $userId
*/
public function controllerLimit($params, $funcName,$userId = 0)
{
foreach ($params as $v) {
if ($v['url'] == $funcName) {
$this->tryLimit($v['url'], "urlLimit:".$userId, $v['time_limit'], $v['try_times'], $v['time_lock']);
}
}
}
/**
* 尝试次数限制
* @param $key
* @param $prefix //前缀,用于跟key组合存redis
* @param $timeLimit // 限制的频率时间
* @param $tryTimes // 限制的次数
* @param $time_lock // 锁死时间
*/
public function tryLimit($key, $prefix, $timeLimit, $tryTimes, $time_lock)
{
if (Yii::$app->redis->exists($key . ':lock:' . $prefix)) {
return $this->end('亲,操作太频繁,稍后再试!');
}
$times = Yii::$app->redis->get($key . $prefix) ?: 0;
if ($times >= $tryTimes) {
// 一小时只能获取$tryTimes次
Yii::$app->redis->setex($key . ':lock:' . $prefix, $time_lock, time());
return $this->end('亲,操作太频繁,稍后再试!');
} else {
Yii::$app->redis->setex($key . $prefix, $timeLimit, $times + 1);
}
}
/*
* 检查是否在不需要拦截的接口列表中
*
* @return bool true=在不需要拦截的接口列表中, false=不在
*/
protected function checkInNoCatch()
{
$moduleID = strtolower(\Yii::$app->controller->module->id); // @todo
$controllerID = strtolower(\Yii::$app->controller->id);
$controllerID = $moduleID . D_S . $controllerID;
$actionID = strtolower(\Yii::$app->controller->action->id);
if (isset($this->_no_catch[$controllerID])) {
$actions = $this->_no_catch[$controllerID];
if (!empty($actions)) {
$actions = array_flip(explode(',', $actions));
if (!isset($actions[$actionID])) {
return false;
}
}
return true;
}
return false;
}
public function beforeAction($action)
{
$this->params = $this->getRequestData();
if ($this->checkInNoCatch() || $this->needLogin == false) {
return true;
} else {
$this->checkParams(['token', 'platform']);
$this->checkToken($this->params['token'], $this->params['platform']);
}
return true;
}
public function afterAction($action, $result)
{
}
public function checkToken($token, $platform)
{
if ($user_id = UserService::getUserInfoByToken($token, $platform, 'user_id')) {
$this->userId = (int)$user_id;
// 根据接口频率锁用户
$uri = Yii::$app->requestedRoute;
if (in_array($uri, [
'user/index/info', 'v2/map/search', 'map/search'
])) {
$this->controllerLimit([
// 指定某接口规则
[
'url' => 'user/index/info',
'time_limit' => 60, // 频率时长 秒
'try_times' => 2, // 次数
'time_lock' => 86400 * 7,// 秒 用户此接口锁XX秒建议锁到活动结束
],
// [
// 'funciton' => 'v2/map/search',
// 'time_limit' => $time_limit,
// 'try_times' => $try_times,
// ],
// [
// 'funciton' => 'map/search',
// 'time_limit' => $time_limit,
// 'try_times' => $try_times,
// ]
], $uri, $this->userId);
}
return true;
} else {
return $this->end('请重新登陆', ErrorCode::ERROR_TOKEN);
}
}
public function render($err, $msg = '', $data = null)
{
$ret = ['status' => $err, 'msg' => $msg];
$ret['data'] = is_null($data) ? (Object)[] : $data;
if (empty($ret['data'])) {
unset($ret['data']);
}
return $ret;
}
public function error($data, $msg = 'Error')
{
return $this->render(ErrorCode::ERROR, $msg, $data);
}
public function success($data, $msg = 'Success')
{
return $this->render(ErrorCode::SUCCESS, $msg, $data);
}
public function getRequestData()
{
$_get = Yii::$app->request->getQueryParams();
$_post = Yii::$app->request->getBodyParams();
$_data = array_merge($_get, $_post);
if ($_data) {
$act = Yii::$app->controller->id . "/" . Yii::$app->controller->action->id;
if (!is_dir(PROJECT_PATH . D_S . 'data' . D_S . 'log')) {
mkdir(PROJECT_PATH . D_S . 'data' . D_S . 'log', 0777, true);
}
file_put_contents(PROJECT_PATH . "/data/log/post-" . date("y-m-d") . ".txt", date('Y-m-d H:i:s') . "[" . $act . "]: " . print_r(json_encode($_data, JSON_UNESCAPED_UNICODE), true) . "\n", FILE_APPEND);
if($this->needSign)
$this->checkSign($_data);
return $_data;
}
return false;
}
public function checkParams($params)
{
}
/**
* 获取客户端ip
* @return string
*/
public function getClientIp()
{
if (getenv('HTTP_CLIENT_IP')) {
$ip = getenv('HTTP_CLIENT_IP');
} else if (getenv('HTTP_X_FORWARDED_FOR')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} else if (getenv('REMOTE_ADDR')) {
$ip = getenv('REMOTE_ADDR');
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
public function checkSign($params)
{
}
public function end($msg = '', $code = ErrorCode::ERROR)
{
$response = yii::$app->response;
$response->format = yii\web\Response::FORMAT_JSON;
$response->data = ['status' => $code, 'msg' => $msg];
$response->send();
\Yii::$app->end();
}
}
|