Initial commit,修正

This commit is contained in:
2025-07-13 19:37:38 +08:00
parent 38ce288e27
commit 65bbd06981
12384 changed files with 3985464 additions and 8 deletions
+339
View File
@@ -0,0 +1,339 @@
<?php
/**
* @author Fm453
* @site www.hiluker.com
* @remark:接口通信证书处理
*/
defined('HI_FM') or exit("Access Denied");
fm_load()->fm_func('fm');
fm_load()->fm_func('file');
//判断某用户证书是否存在
/*
@username 用户名
*/
function fmFunc_cert_exist($username)
{
global $_GPC;
global $_HI;
global $_FM;
$file = $_HI['apiCertPath'].$username.'.php';
if(file_exists($file)){
$cert = require($file);
return $cert;
}
return false;
}
//登陆前,根据来路判断访问是否合规
/*
@username 用户名
@ip 来路IP
@domain 来路域名
*考虑到CDN加速导致IP变化的原因,域名或IP有一个符合规则即可
*/
function fmFunc_cert_beforeLogin($cert,$ip,$domain)
{
global $_GPC;
global $_HI;
global $_FM;
if(!is_array($cert) && !empty($cert)){
//未引入证书时,不判断
return true;
}elseif(empty($ip) && empty($domain)){
//ip与domain均未传入时,不判断
return true;
}
$ips = isset($cert['suIp']) ? $cert['suIp'] : false;
$domains = isset($cert['suDomain']) ? $cert['suDomain'] : false;
$username = isset($cert['api']) ? $cert['api'] : false;
if(!$ips || !$domains || !$username){
//没有有效的证书配置时,不判断
return true;
}
//为fm453本地开发放行,为公共密钥publicapi放行
if($username == 'vcms.localhost' || $username == 'publicapi') {
return true;
}
//判断ip与domain的合法性
if(!in_array($ip,$ips) && !in_array($domain,$domains)){
return false;
}
return true;
}
//登陆后,更新证书
/*
*有则更新,无则创建
*/
function fmFunc_cert_afterLogin(){
global $_GPC;
global $_HI;
global $_FM;
if(!isset($_FM['user']['name'])){
return false;
}
$_FM['viaDomain'] = isset($_FM['viaDomain']) ? $_FM['viaDomain'] : fmFunc_server_via_domain();
$_FM['viaIp'] = isset($_FM['viaIp']) ? $_FM['viaIp'] : fmFunc_server_via_ip();
$connection = yii::$app->db;
//客户侧是否请求刷新token;否,则直接取token值后返回(应对同一账号同一站点多模块使用的情况)(同一账号,同一站点对应同一token;同一账号可拥有多个token)
if(!isset($_GET['refreshToken']) || empty($_GET['refreshToken'])){
$sql = "SELECT `accesstoken` FROM c_access WHERE username = :username AND ip = :ip AND domain = :domain ORDER BY id ASC";
$params = array();
$params[':username'] = $_FM['user']['name'];
$params[':ip'] = $_FM['viaIp'];
$params[':domain'] = $_FM['viaDomain'];
//$AccessToken = fmFunc_pdo_yii_fetchcolumn($connection,$sql, $params);
$AccessToken = fmFunc_pdo_yii_fetchcolumn($connection,$table='c_access', $column='accesstoken', $conditions = 'username = :username AND ip = :ip AND domain = :domain ORDER BY id ASC', $params);
$_FM['token'] = $AccessToken;
//cert证书文件
//如果没有,创建之;如果有,更新其中的token
$username = $_FM['user']['name'];
$cert = fmFunc_cert_exist($username);
if(!$cert){
$cert = array();
$cert['id'] = $_FM['user']['uid'];
$cert['siteId'] = $_FM['timestamp'];
$cert['suIp'] = array($_FM['viaIp']);
$cert['siteName'] = '';
$cert['suDomain'] = array($_FM['viaDomain']);
$cert['siteUrl'] = '';
$cert['api'] = $username;
$cert['code'] = '';
$cert['token'] = $AccessToken;
$cert['status'] = '0';
$cert['remark'] = '新创建待审核,创建时间:'.date('Y-m-d H:i:s',$_FM['timestamp']);
}
$_FM['apiCert'] = $cert;
fmFunc_cert_write($username,$cert);
if($AccessToken) {
return;
}
}
//生成一个新AccssToken
/*
*生成方法:
@md5: 用户名username+编码useruid+当前时间戳timestamp+失效时间expiretime+随机混淆码randchars 拼接
*/
$randchars = randchars(5);
$content = array();
$content[] = $_FM['user']['name'];
$content[] = $_FM['user']['uid'];
$content[] = $_FM['timestamp'];
$content[] = $expiretime = 3600 * 24 * 30;
$content[] = $randchars;
$_content = iserializer($content);
$AccessToken = md5($_content);
$_FM['token'] = $AccessToken;
//在c_access表中记录登陆对应的有效token
$initdata = array();
$initdata['accesstoken'] = $AccessToken;
$initdata['updatetime'] = $_FM['timestamp'];
$initdata['expiretime'] = $_FM['timestamp']+$expiretime;
$initdata['hashchars'] = $randchars;
$sql = "SELECT `id` FROM c_access WHERE username = :username AND ip = :ip AND domain = :domain ORDER BY id ASC";
$params = array();
$params[':username'] = $_FM['user']['name'];
$params[':ip'] = $_FM['viaIp'];
$params[':domain'] = $_FM['viaDomain'];
$hasId = fmFunc_pdo_yii_fetch($connection,$sql, $params);
if($hasId) {
$condition = 'username = :username AND ip = :ip AND domain = :domain';
fmFunc_pdo_yii_update($connection, 'c_access', $initdata, $condition, $params);
}else{
$initdata['username'] = $_FM['user']['name'];
$initdata['uid'] = $_FM['user']['uid'];
$initdata['userType'] = 2; //客户系统侧的用户登陆,统一归为user类型(接口使用者)
$initdata['ip'] = $_FM['viaIp'];
$initdata['domain'] = $_FM['viaDomain'];
$initdata['data'] = $_content;
$initdata['create_time'] = date('y-m-d H:i:s',$_FM['timestamp']);
fmFunc_pdo_yii_insert($connection, 'c_access', $initdata);
}
//cert证书文件进一步校验
//如果没有,创建之;如果有,更新其中的token
$username = $_FM['user']['name'];
$cert = fmFunc_cert_exist($username);
if(!$cert){
$cert = array();
$cert['id'] = $_FM['user']['uid'];
$cert['siteId'] = $_FM['timestamp'];
$cert['suIp'] = array($_FM['viaIp']);
$cert['siteName'] = '';
$cert['suDomain'] = array($_FM['viaDomain']);
$cert['siteUrl'] = '';
$cert['api'] = $username;
$cert['code'] = '';
$cert['token'] = $AccessToken;
$cert['status'] = '0';
$cert['remark'] = '新创建待审核,创建时间:'.date('Y-m-d H:i:s',$_FM['timestamp']);
}elseif(is_array($cert)){
$cert['token'] = $AccessToken;
$cert['updatetime'] = '更新时间:'.date('Y-m-d H:i:s',$_FM['timestamp']);
}
fmFunc_cert_write($username,$cert);
}
//为指定用户写证书
/*
@username 用户名
@cert 证书内容
*/
function fmFunc_cert_write($username,$cert)
{
global $_GPC;
global $_HI;
global $_FM;
if(!$username){
return false;
}
$file = $_HI['apiCertPath'].$username.'.php';
$content = "<?php";
$content .= "\r\n";
$content .= "/*";
$content .= "\r\n";
$content .= "* 通讯证书文件";
$content .= "\r\n";
$content .= "@status 站点状态,-1禁止 0只读 1可用";
$content .= "\r\n";
$content .= "@siteId 站点ID";
$content .= "\r\n";
$content .= "@suIp 允许访问的IP";
$content .= "\r\n";
$content .= "@suDomain 允许访问的域名";
$content .= "\r\n";
$content .= "@api 接口用户名(站点用户名)";
$content .= "\r\n";
$content .= "@code 用户授权码";
$content .= "\r\n";
$content .= "@token 接口通讯的accesstoken文件";
$content .= "\r\n";
$content .= "*/";
$content .= "\r\n";
$content .= "\$cert = array();";
$content .= "\r\n";
foreach($cert as $k=>$v){
if(!is_array($v)) {
$content .= "\$cert['".$k."'] = '".(string)$v."';";
}else{
$content .= "\$cert['".$k."'] = array(";
$len = count($v);
for($i = $len;$i>0;$i--){
if($i>1) {
$content .= "'".(string)$v[$i-1]."',";
}elseif($i==1) {
$content .= "'".(string)$v[$i-1]."'";
}
}
$content .= ");";
}
$content .= "\r\n";
}
$content .= "return \$cert;";
$content .= "\r\n";
fmFunc_file_write($file,$content);
}
/*__________________________________________________*/
//根据请求数据返回通讯授权结果(0为正常,>0表示错误代码)
/*
*判断机制:
(1)get方式接收到username与accesstoken,判断是否匹配
(2)username对应的证书文件是否存在
(3)根据证书检测是否合规的访问
*/
function fmFunc_cert_checkAuth(){
global $_GPC;
global $_HI;
global $_FM;
//检查appid
if(!isset($_FM['get']['appid'])){
return 45300205; //未指定有效的appid
}elseif(empty($_FM['get']['appid'])){
return 45300205; //未指定有效的appid
}
//检查accesstoken
if(!isset($_FM['get']['accesstoken'])){
return 45300204; //未指定有效的accesstoken
}elseif(empty($_FM['get']['accesstoken'])){
return 45300204; //未指定有效的accesstoken
}
//检查appid与accesstoken是否匹配
$username = $_FM['get']['appid'];
$accesstoken = $_FM['get']['accesstoken'];
$connection = yii::$app->db;
$sql = "SELECT `id` FROM c_access WHERE username = :username AND accesstoken = :accesstoken ";
$params = array();
$params[':username'] = $username;
$params[':accesstoken'] = $accesstoken;
$hasId = fmFunc_pdo_yii_fetch($connection,$sql, $params);
if(!$hasId){
return 45300206; //不匹配
}
//设置用户为登陆状态
$_FM['user']['name'] = $username;
// 使用指定用户名获取用户身份实例
$User = new common\models\User;
$identity = $User->findOne(['username' => $_FM['user']['name']]);
$_FM['user']['uid'] = $identity->id;
// 登录用户,有效期30d
$duration = 3600 * 24 * 30;
Yii::$app->user->login($identity, $duration);
//查询服务器证书
$cert = fmFunc_cert_exist($username);
if(!$cert){
return 45300104; //未查询到服务器证书
}
//检查证书有效性
$ips = isset($cert['suIp']) ? $cert['suIp'] : false;
$domains = isset($cert['suDomain']) ? $cert['suDomain'] : false;
$api = (isset($cert['api']) && !empty($cert['api'])) ? $cert['api'] : false;
if((!$ips && !$domains) || !$api){
return 45300105; //无效的证书
}
//来路域名与IP
$_FM['viaDomain'] = isset($_FM['viaDomain']) ? $_FM['viaDomain'] : fmFunc_server_via_domain();
$_FM['viaIp'] = isset($_FM['viaIp']) ? $_FM['viaIp'] : fmFunc_server_via_ip();
//为fm453本地开发放行,为公共密钥publicapi放行,其他来路均需判断合法性
if($username != 'vcms.localhost' && $username != 'publicapi') {
//判断ip与domain的合法性
if(!in_array($_FM['viaIp'],$ips) && !in_array($_FM['viaDomain'],$domains)){
return 45300101; //来源IP或域名不在白名单中
}
}
$_FM['apiCert'] = $cert;
return 0;
}