This commit is contained in:
2025-11-21 01:42:54 +08:00
parent ff026c6f32
commit f89196c73c
1953 changed files with 9 additions and 15246 deletions
+528
View File
@@ -0,0 +1,528 @@
<?php
namespace support;
use app\model\User;
use app\model\UserRule;
use support\think\Db;
class Jwt
{
protected static $instance = null;
protected static $_error = '';
protected static $_logined = false;
protected static $_user = null;
protected static $_token = '';
//Token默认有效时长
protected static $keeptime = 2592000;
protected static $requestUri = '';
protected static $rules = [];
//默认配置
protected static $config = [];
protected static $options = [];
protected static $disallowFields = [
'password','trade_password','totp_secret',//安全信息
'created_at','updated_at','loginfailure',//系统信息
//'last_time','last_ip','join_time','join_ip',最近登录信息
//'score',
'level',
];
/**
* 注册用户
*
* @param string $username 用户名
* @param string $password 密码
* @param string $email 邮箱
* @param string $mobile 手机号
* @param array $extend 扩展参数
* @return boolean
*/
public static function register($username, $password, $email = '', $mobile = '', $extend = []): array|bool
{
// 检测用户名、昵称、邮箱、手机号是否存在
if (User::getByUsername($username)) {
self::setError('Username already exist');
return false;
}
if (User::getByNickname($username)) {
self::setError('Nickname already exist');
return false;
}
if ($email && User::getByEmail($email)) {
self::setError('Email already exist');
return false;
}
if ($mobile && User::getByMobile($mobile)) {
self::setError('Mobile already exist');
return false;
}
$request = request();
if($request){
$ip = getRealIp();
}else{
$ip = '127.0.0.1';
}
$time = time();
$data = [
'username' => $username,
'password' => $password,
'email' => $email,
'mobile' => $mobile,
'level' => 1,
'score' => 0,
'avatar' => '',
];
$params = array_merge($data, [
'nickname' => preg_match("/^1[3-9]{1}\d{9}$/", $username) ? substr_replace($username, '****', 3, 4) : $username,
//'salt' => Random::alnum(),
'join_time' => $time,
'join_ip' => $ip,
'last_time' => $time,
'last_ip' => $ip,
'status' => '1'
]);
$params['password'] = \plugin\admin\app\common\Util::passwordHash($password);
$params = array_merge($params, $extend);
//账号注册时需要开启事务,避免出现垃圾数据
Db::startTrans();
try {
$user = User::create($params,[], true);
/**
* @var User $user
* */
$user->role_id;
$user = User::where('id',$user->id)->find();
$user['client'] = \support\Jwt\JwtToken::TOKEN_CLIENT_WEB;
if(Request()->client == 'win'){
$user['client'] = \support\Jwt\JwtToken::TOKEN_CLIENT_PC;
\support\Jwt\JwtToken::clear(\support\Jwt\JwtToken::TOKEN_CLIENT_PC);
}
$_token = \support\Jwt\JwtToken::generateToken($user->toArray());
$user->token = $_token['access_token'];
Db::commit();
//注册成功的事件
Hook("user.register_successed", $user);
return self::getUserinfo($user);
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
}
/**
* 用户登录
*
* @param string $account 账号,用户名、邮箱、手机号
* @param string $password 密码
* @return boolean
*/
public static function login($account, $password,$type=''): array|bool
{
if($type){
$field = $type;
}else{
$field = strpos('@',$account)!==false ? 'email' : 'username';
}
/**
* @var User $user
* */
if($field=='mobile'){
$user = User::where($field , $account)->where('region',Request()->post('region'))->find();
}else{
$user = User::where($field , $account)->find();
}
if (!$user) {
self::setError('Account is incorrect');
return false;
}
if ($user->status != 1) {
self::setError('Account is locked');
return false;
}
//if ($user->username!='' && !\plugin\admin\app\common\Util::passwordVerify($password,$user->password)) {
if (!\plugin\admin\app\common\Util::passwordVerify($password,$user->password)) {
self::setError('Password is incorrect');
return false;
}
//直接登录会员
return self::direct($user->id);
}
/**
* 退出
*
* @return boolean
*/
public static function logout()
{
//退出成功的事件
Hook("user.logout_successed");
return true;
}
/**
* 修改密码
* @param string $newpassword 新密码
* @param string $oldpassword 旧密码
* @param bool $ignoreoldpassword 忽略旧密码
* @return boolean
*/
public static function changepwd($newpassword, $oldpassword = '', $ignoreoldpassword = false)
{
if (!self::isLogin()) {
self::setError('You are not logged in');
return false;
}
$user = self::getUser();
//判断旧密码是否正确
if (!\plugin\admin\app\common\Util::passwordVerify($oldpassword,$user->password) || $ignoreoldpassword) {
Db::startTrans();
try {
$salt = Random::alnum();
User::where('id',$user->id)->save([
'loginfailure' => 0,
'password' => \plugin\admin\app\common\Util::passwordHash($newpassword)
]);
//修改密码成功的事件
Hook("user.changepwd_successed", $user);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
return true;
} else {
self::setError('Password is incorrect');
return false;
}
}
/**
* 修改交易密码
* @param string $newpassword 新密码
* @param string $oldpassword 旧密码
* @param bool $ignoreoldpassword 忽略旧密码
* @return boolean
*/
public static function change_trade_pwd($newpassword, $oldpassword = '', $ignoreoldpassword = false)
{
$user = self::getUser();
if (!self::isLogin()) {
self::setError('You are not logged in');
return false;
}
//判断旧密码是否正确
if (!$user->trade_password || $ignoreoldpassword || \plugin\admin\app\common\Util::passwordVerify($oldpassword,$user->trade_password)) {
Db::startTrans();
try {
$salt = Random::alnum();
User::where('id',$user->id)->save(['trade_password' => \plugin\admin\app\common\Util::passwordHash($newpassword)]);
//修改密码成功的事件
Hook("user.change_trade_pwd_successed", $user);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
return true;
} else {
self::setError('Old password is incorrect');
return false;
}
}
static function verify_trade_password($password){
$user = self::getUser();
if(is_null($user->trade_password)){
throw new \Exception(__('Please set the trade password first'),200);
}
if (!\plugin\admin\app\common\Util::passwordVerify($password,$user->trade_password)) {
throw new \Exception(__('Trade password is incorrect'),200);
}
}
/**
* 直接登录账号
* @param int $user_id
* @return boolean
*/
public static function direct($user_id): array|bool
{
$user = User::where('id',$user_id)->find();
if ($user) {
Db::startTrans();
try {
$ip = getRealIp();
$time = time();
//记录本次登录的IP和时间
$user->last_ip = $ip;
$user->last_time = $time;
//重置登录失败次数
$user->loginfailure = 0;
$user->save();
Db::commit();
$user['client'] = \support\Jwt\JwtToken::TOKEN_CLIENT_WEB;
if(Request()->client == 'win'){
$user['client'] = \support\Jwt\JwtToken::TOKEN_CLIENT_PC;
//\support\Jwt\JwtToken::clear(\support\Jwt\JwtToken::TOKEN_CLIENT_PC);
}
$_user = $user->toArray();
$_user = [
'id' => $_user['id'],
'username' => $_user['username'],
'client' => $_user['client'],
];
$_token = \support\Jwt\JwtToken::generateToken($_user);
$user->token = $_token['access_token'];
//登录成功的事件
Hook("user.login_successed", $user);
return self::getUserinfo($user);
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
} else {
return false;
}
}
/**
* 检测是否是否有对应权限
* @param string $path 控制器/方法
* @param string $module 模块 默认为当前模块
* @return boolean
*/
public static function check($path = null, $module = null)
{
if (!self::isLogin()) {
return false;
}
$ruleList = self::getRuleList();
$rules = [];
foreach ($ruleList as $k => $v) {
$rules[] = $v['key'];
}
$url = ($module ? $module : request()->app) . '/' . (is_null($path) ? self::getRequestUri() : $path);
$url = strtolower(str_replace('.', '/', $url));
return in_array($url, $rules);
}
/**
* 判断是否登录
* @return boolean
*/
public static function isLogin()
{
$user_id = \support\Jwt\JwtToken::getCurrentId();
if ($user_id) {
return true;
}
return false;
}
/**
* 获取User模型
* @return User
*/
public static function getUser($user=null)
{
$user = $user ? $user : \support\Jwt\JwtToken::getUser();
return $user;
}
/**
* 获取会员基本信息
*/
public static function getUserinfo($user=null)
{
$data = self::getUser($user)->toArray();
$disallowFields = self::getDisallowFields();
$userinfo = array_diff_key($data, array_flip($disallowFields));
$userinfo['has_trade_password'] = $data['trade_password'] ? true: false;
return $userinfo;
}
/**
* 获取会员组别规则列表
* @return array|bool|\PDOStatement|string|\think\Collection
*/
public static function getRuleList()
{
$user = self::getUser();
$role_id = $user->role_id;
if (!$role_id) {
return [];
}
if (cache('group_rules_'.$role_id)) {
return cache('group_rules_'.$role_id);
}
$rules = explode(',', $role_id);
$rules = UserRule::where('status', 'normal')->where('id', 'in', $rules)->field('id,pid,key,title,type')->select();
cache('group_rules_'.$role_id,$rules);
return $rules;
}
/**
* 获取当前请求的URI
* @return string
*/
public static function getRequestUri()
{
return self::$requestUri;
}
/**
* 设置当前请求的URI
* @param string $uri
*/
public static function setRequestUri($uri)
{
self::$requestUri = $uri;
}
/**
* 获取允许输出的字段
* @return array
*/
public static function getDisallowFields()
{
return self::$disallowFields;
}
/**
* 设置允许输出的字段
* @param array $fields
*/
public static function setDisallowFields($fields)
{
self::$disallowFields = $fields;
}
/**
* 删除一个指定会员
* @param int $user_id 会员ID
* @return boolean
*/
public static function delete($user_id)
{
$user = User::where('id',$user_id)->find();
if (!$user) {
return false;
}
Db::startTrans();
try {
// 删除会员
User::destroy($user_id);
Hook("user.delete_successed", $user);
Db::commit();
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
return true;
}
/**
* 获取密码加密后的字符串
* @param string $password 密码
* @param string $salt 密码盐
* @return string
*/
public function getEncryptPassword($password, $salt = '')
{
return md5(md5($password) . $salt);
}
/**
* 检测当前控制器和方法是否匹配传递的数组
*
* @param array $arr 需要验证权限的数组
* @return boolean
*/
public static function match($arr = [])
{
$request = Request();
$arr = is_array($arr) ? $arr : explode(',', $arr);
if (!$arr) {
return false;
}
$arr = array_map('strtolower', $arr);
// 是否存在
if (in_array(strtolower($request->action), $arr) || in_array('*', $arr)) {
return true;
}
// 没找到匹配
return false;
}
/**
* 渲染用户数据
* @param array $datalist 二维数组
* @param mixed $fields 加载的字段列表
* @param string $fieldkey 渲染的字段
* @param string $renderkey 结果字段
* @return array
*/
public function render(&$datalist, $fields = [], $fieldkey = 'user_id', $renderkey = 'userinfo')
{
$fields = !$fields ? ['id', 'nickname', 'level', 'avatar'] : (is_array($fields) ? $fields : explode(',', $fields));
$ids = [];
foreach ($datalist as $k => $v) {
if (!isset($v[$fieldkey])) {
continue;
}
$ids[] = $v[$fieldkey];
}
$list = [];
if ($ids) {
if (!in_array('id', $fields)) {
$fields[] = 'id';
}
$ids = array_unique($ids);
$selectlist = User::where('id', 'in', $ids)->column($fields);
foreach ($selectlist as $k => $v) {
$list[$v['id']] = $v;
}
}
foreach ($datalist as $k => &$v) {
$v[$renderkey] = $list[$v[$fieldkey]] ?? null;
}
unset($v);
return $datalist;
}
/**
* 设置错误信息
*
* @param string $error 错误信息
* @return void
*/
public static function setError($error)
{
self::$_error = $error;
abort($error);
}
/**
* 获取错误信息
* @return string
*/
public static function getError()
{
return self::$_error ? __(self::$_error) : '';
}
}