2021-02-02 07:48:07 +00:00
|
|
|
|
<?php
|
|
|
|
|
namespace app\domain;
|
|
|
|
|
|
|
|
|
|
use support\Request;
|
2021-02-03 11:36:54 +00:00
|
|
|
|
use app\common\exception\BusinessException;
|
2021-02-02 07:48:07 +00:00
|
|
|
|
use app\common\components\Curl;
|
|
|
|
|
use app\common\Constant;
|
2021-07-18 08:23:17 +00:00
|
|
|
|
use app\common\Config as Conf;
|
2021-02-02 07:48:07 +00:00
|
|
|
|
|
|
|
|
|
/**
|
2021-07-18 08:23:17 +00:00
|
|
|
|
* 用户逻辑操作 [无状态静态类]
|
2021-02-02 07:48:07 +00:00
|
|
|
|
* @access private 常驻内存运行,禁止执行器调用
|
|
|
|
|
*/
|
|
|
|
|
class Users
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* 检查用户Session是否已登录
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public static function isLogin(Request $request):bool
|
|
|
|
|
{
|
|
|
|
|
$session = $request->session();
|
2021-07-04 15:14:33 +00:00
|
|
|
|
$has = $session->has(Constant::Session_Token_Key);
|
2021-02-02 07:48:07 +00:00
|
|
|
|
return $has ? true : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 检查token及绑定状态
|
2021-07-18 08:23:17 +00:00
|
|
|
|
* - 接口api.iyuu.cn返回的信息,原样返回给前端
|
|
|
|
|
* @descr 接口地址 https://api.iyuu.cn/index.php?s=App.Api.Sites
|
|
|
|
|
* 接口文档 https://api.iyuu.cn/docs.php?service=App.Api.Sites&detail=1&type=fold
|
2021-02-02 07:48:07 +00:00
|
|
|
|
* @param string $token
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function checkToken(string $token, Request $request):array
|
|
|
|
|
{
|
|
|
|
|
$curl = Curl::one();
|
|
|
|
|
$api_url = Constant::API_BASE;
|
|
|
|
|
$api_action = Constant::API['sites'];
|
|
|
|
|
$url = sprintf('%s%s?sign=%s&version=%s', $api_url, $api_action, $token, IYUU_VERSION());
|
2021-08-10 15:47:52 +00:00
|
|
|
|
file_put_contents(db_path().'/_url.json',print_r($url, true));
|
2021-02-02 07:48:07 +00:00
|
|
|
|
$res = $curl->get($url);
|
|
|
|
|
$rs = json_decode($res->response, true);
|
2021-08-23 02:52:14 +00:00
|
|
|
|
if (empty($res->response) || empty($rs) || !is_array($rs)) {
|
|
|
|
|
$rs = Constant::RS;
|
|
|
|
|
$rs['ret'] = 500;
|
2021-08-23 03:06:10 +00:00
|
|
|
|
$rs['msg'] = "无法访问{$api_url}接口,请检查本地网络;或重新创建容器,网络模式改为HOST模式。";
|
2021-08-23 02:52:14 +00:00
|
|
|
|
return $rs;
|
|
|
|
|
}
|
2021-08-10 14:36:58 +00:00
|
|
|
|
file_put_contents(db_path().'/_response.json',print_r($res->response, true));
|
2021-07-04 15:14:33 +00:00
|
|
|
|
if (isset($rs['ret']) && ($rs['ret'] === 200) && isset($rs['data']['sites']) && is_array($rs['data']['sites'])) {
|
2021-02-02 07:48:07 +00:00
|
|
|
|
$sites = array_column($rs['data']['sites'], null, 'site');
|
2021-07-18 08:23:17 +00:00
|
|
|
|
Conf::set('sites', $sites, Constant::config_format);
|
|
|
|
|
Conf::set('iyuu', ['iyuu.cn' => $token], Constant::config_format);
|
2021-02-04 19:00:31 +00:00
|
|
|
|
// 验证通过,写入Session
|
|
|
|
|
$session = $request->session();
|
|
|
|
|
$session->set(Constant::Session_Token_Key, $token);
|
2021-02-02 07:48:07 +00:00
|
|
|
|
} else {
|
2021-07-18 08:23:17 +00:00
|
|
|
|
/**
|
|
|
|
|
* 接口api.iyuu.cn在用户的token未激活时,会返回403状态码 和 推荐站点列表,供用户填写绑定信息
|
|
|
|
|
*/
|
2021-07-04 15:14:33 +00:00
|
|
|
|
if (isset($rs['ret']) && ($rs['ret'] === 403) && isset($rs['data']['recommend']) && is_array($rs['data']['recommend'])) {
|
2021-02-02 07:48:07 +00:00
|
|
|
|
//用户未绑定合作站点
|
|
|
|
|
$recommend = $rs['data']['recommend'];
|
2021-07-18 08:23:17 +00:00
|
|
|
|
Conf::set('recommend', $recommend, Constant::config_format);
|
|
|
|
|
Conf::set('iyuu', ['iyuu.cn' => $token], Constant::config_format);
|
2021-02-02 07:48:07 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $rs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用户绑定
|
|
|
|
|
* @descr 接口地址 https://api.iyuu.cn/index.php?s=App.User.Login
|
|
|
|
|
* 接口文档 https://api.iyuu.cn/docs.php?service=App.User.Login&detail=1&type=fold
|
|
|
|
|
* @param string $token
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public static function bindToken(string $token, Request $request):array
|
|
|
|
|
{
|
|
|
|
|
$curl = Curl::one();
|
|
|
|
|
$url = Constant::API_BASE . Constant::API['login'];
|
|
|
|
|
$data = [
|
|
|
|
|
'token' => $token,
|
|
|
|
|
'id' => $request->post('id') + 0,
|
|
|
|
|
'passkey'=> sha1($request->post('passkey')), // 避免泄露用户passkey秘钥
|
|
|
|
|
'site' => $request->post('site'),
|
|
|
|
|
];
|
|
|
|
|
$res = $curl->get($url, $data);
|
|
|
|
|
$rs = json_decode($res->response, true);
|
2021-08-23 03:06:10 +00:00
|
|
|
|
if (empty($res->response) || empty($rs) || !is_array($rs)) {
|
|
|
|
|
$rs = Constant::RS;
|
|
|
|
|
$rs['ret'] = 500;
|
|
|
|
|
$rs['msg'] = "无法访问{$url}接口,请检查本地网络;或重新创建容器,网络模式改为HOST模式。";
|
|
|
|
|
return $rs;
|
|
|
|
|
}
|
2021-02-02 07:48:07 +00:00
|
|
|
|
if (isset($rs['ret']) && ($rs['ret'] === 200) && isset($rs['data']['success']) && $rs['data']['success']) {
|
|
|
|
|
//绑定成功
|
|
|
|
|
return self::checkToken($token, $request);
|
|
|
|
|
} else {
|
|
|
|
|
//绑定失败
|
2021-02-06 11:30:47 +00:00
|
|
|
|
$rs['ret'] = 401;
|
2021-02-02 07:48:07 +00:00
|
|
|
|
$msg = !empty($rs['msg']) ? $rs['msg'] : '远端服务器无响应,请稍后重试!';
|
|
|
|
|
$msg = !empty($rs['data']['errmsg']) ? $rs['data']['errmsg'] : $msg;
|
|
|
|
|
$rs['msg'] = $msg;
|
|
|
|
|
return $rs;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-03 11:36:54 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 验证用户输入的密码
|
|
|
|
|
* @param Request $request
|
|
|
|
|
* @return bool
|
|
|
|
|
* @throws BusinessException
|
|
|
|
|
*/
|
|
|
|
|
public static function checkPassword(Request $request):bool
|
|
|
|
|
{
|
|
|
|
|
$password = $request->get('password');
|
|
|
|
|
if (empty($password)) {
|
|
|
|
|
throw new BusinessException('密码不能为空', 250);
|
|
|
|
|
}
|
2021-07-18 08:23:17 +00:00
|
|
|
|
$userProfile = Conf::get(self::getUserProfileName(), 'json');
|
2021-02-03 11:36:54 +00:00
|
|
|
|
if (is_null($userProfile)) {
|
|
|
|
|
//初次使用,设置用户密码
|
|
|
|
|
return self::setPassword($password);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//验证密码
|
|
|
|
|
$salt = $userProfile['salt'];
|
|
|
|
|
if ($userProfile['pass_hash'] !== self::createPassHash($password, $salt)) {
|
|
|
|
|
throw new BusinessException('密码错误,请重新输入!',250);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置用户密码
|
|
|
|
|
* @param string $password
|
|
|
|
|
* @return bool
|
|
|
|
|
* @throws BusinessException
|
|
|
|
|
*/
|
|
|
|
|
public static function setPassword(string $password):bool
|
|
|
|
|
{
|
|
|
|
|
//粗略验证
|
|
|
|
|
if (strlen($password) < 6) {
|
|
|
|
|
throw new BusinessException('密码必须超过6位', 250);
|
|
|
|
|
}
|
|
|
|
|
if (in_array($password, ['admin','root','adminadmin','administrator'])) {
|
|
|
|
|
throw new BusinessException('密码太弱,不安全', 250);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$salt = getUUID(); //太淡了,加点盐
|
|
|
|
|
$userProfile = [
|
|
|
|
|
'pass_hash' => self::createPassHash($password, $salt),
|
|
|
|
|
'salt' => $salt,
|
|
|
|
|
'created_at' => time()
|
|
|
|
|
];
|
|
|
|
|
|
2021-07-18 08:23:17 +00:00
|
|
|
|
return Conf::set(self::getUserProfileName(), $userProfile, 'json');
|
2021-02-03 11:36:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成密码hash
|
|
|
|
|
* @param string $password
|
|
|
|
|
* @param string $salt
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public static function createPassHash(string $password, string $salt):string
|
|
|
|
|
{
|
|
|
|
|
return md5($salt . $password . $salt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用户特征文件名
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public static function getUserProfileName():string
|
|
|
|
|
{
|
|
|
|
|
return 'userProfile';
|
|
|
|
|
}
|
2021-02-02 07:48:07 +00:00
|
|
|
|
}
|