2022-08-19 19:48:37 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | swiftAdmin 极速开发框架 [基于WebMan开发]
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Copyright (c) 2020-2030 http://www.swiftadmin.net
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | swiftAdmin.net High Speed Development Framework
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
// | Author: meystack <coolsec@foxmail.com> Apache 2.0 License
|
|
|
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
namespace app\common\library;
|
|
|
|
|
|
2022-11-28 19:11:12 +08:00
|
|
|
use app\common\model\system\UserLog;
|
2022-12-02 11:16:57 +08:00
|
|
|
use Psr\SimpleCache\InvalidArgumentException;
|
2022-08-19 19:48:37 +08:00
|
|
|
use system\Random;
|
|
|
|
|
use support\Response;
|
2022-12-02 11:16:57 +08:00
|
|
|
use think\db\exception\DataNotFoundException;
|
|
|
|
|
use think\db\exception\DbException;
|
|
|
|
|
use think\db\exception\ModelNotFoundException;
|
2022-08-19 19:48:37 +08:00
|
|
|
use think\facade\Cache;
|
|
|
|
|
use app\common\model\system\User as UserModel;
|
|
|
|
|
use Webman\Event\Event;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Auth
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* token令牌
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2022-11-28 19:11:12 +08:00
|
|
|
public string $token;
|
2022-08-19 19:48:37 +08:00
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
/**
|
|
|
|
|
* 用户ID
|
|
|
|
|
*/
|
2023-04-25 20:11:49 +08:00
|
|
|
public mixed $user_id = 0;
|
2022-12-02 11:16:57 +08:00
|
|
|
|
2022-08-19 19:48:37 +08:00
|
|
|
/**
|
|
|
|
|
* 用户数据
|
|
|
|
|
* @var object|array
|
|
|
|
|
*/
|
2022-12-02 11:16:57 +08:00
|
|
|
public mixed $userInfo;
|
2022-08-19 19:48:37 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 保活时间
|
2022-11-28 19:11:12 +08:00
|
|
|
* @var int
|
2022-08-19 19:48:37 +08:00
|
|
|
*/
|
2022-11-28 19:11:12 +08:00
|
|
|
protected int $keepTime = 604800;
|
2022-08-19 19:48:37 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 错误信息
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2022-11-28 19:11:12 +08:00
|
|
|
protected string $_error = '';
|
2022-08-19 19:48:37 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var object 对象实例
|
|
|
|
|
*/
|
2022-11-28 19:11:12 +08:00
|
|
|
protected static $instance;
|
2022-08-19 19:48:37 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 类构造函数
|
|
|
|
|
* class constructor.
|
|
|
|
|
*/
|
|
|
|
|
public function __construct($config = [])
|
|
|
|
|
{
|
|
|
|
|
$this->keepTime = config('session.cookie_lifetime');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 初始化
|
|
|
|
|
* @access public
|
|
|
|
|
* @param array $options 参数
|
|
|
|
|
* @return object
|
|
|
|
|
*/
|
|
|
|
|
public static function instance(array $options = [])
|
|
|
|
|
{
|
|
|
|
|
if (is_null(self::$instance)) {
|
|
|
|
|
self::$instance = new static($options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回实例
|
|
|
|
|
return self::$instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用户注册
|
|
|
|
|
* @param array $post
|
2022-12-02 11:16:57 +08:00
|
|
|
* @return false|Response
|
|
|
|
|
* @throws DataNotFoundException
|
|
|
|
|
* @throws DbException
|
|
|
|
|
* @throws InvalidArgumentException
|
|
|
|
|
* @throws ModelNotFoundException
|
2022-08-19 19:48:37 +08:00
|
|
|
*/
|
|
|
|
|
public function register(array $post)
|
|
|
|
|
{
|
|
|
|
|
if (!saenv('user_status')) {
|
|
|
|
|
$this->setError('暂未开放注册!');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
// 禁止批量注册
|
|
|
|
|
$where[] = ['create_ip', '=', request()->getRealIp()];
|
2023-04-25 20:11:49 +08:00
|
|
|
$where[] = ['create_time', '>', linux_time(1)];
|
2022-08-19 19:48:37 +08:00
|
|
|
$totalMax = UserModel::where($where)->count();
|
|
|
|
|
|
|
|
|
|
if ($totalMax >= saenv('user_register_second')) {
|
|
|
|
|
$this->setError('当日注册量已达到上限');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 过滤用户信息
|
|
|
|
|
if (isset($post['nickname']) && UserModel::getByNickname($post['nickname'])) {
|
|
|
|
|
$this->setError('当前用户名已被占用!');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($post['email']) && UserModel::getByEmail($post['email'])) {
|
|
|
|
|
$this->setError('当前邮箱已被占用!');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($post['mobile']) && UserModel::getByMobile($post['mobile'])) {
|
|
|
|
|
$this->setError('当前手机号已被占用!');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
/**
|
|
|
|
|
* 是否存在邀请注册
|
|
|
|
|
*/
|
|
|
|
|
$post['invite_id'] = $this->getToken('inviter');
|
|
|
|
|
if (isset($post['pwd']) && $post['pwd']) {
|
|
|
|
|
$post['salt'] = Random::alpha();
|
|
|
|
|
$post['pwd'] = encryptPwd($post['pwd'], $post['salt']);
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
$user = UserModel::create($post);
|
2022-08-19 19:48:37 +08:00
|
|
|
} catch (\Throwable $th) {
|
|
|
|
|
$this->setError($th->getMessage());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-12-02 11:16:57 +08:00
|
|
|
|
|
|
|
|
return $this->responseToken($user);
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 用户检测登录
|
|
|
|
|
* @param string $nickname
|
|
|
|
|
* @param string $pwd
|
2022-12-02 11:16:57 +08:00
|
|
|
* @return false|Response
|
|
|
|
|
* @throws DataNotFoundException
|
|
|
|
|
* @throws DbException
|
|
|
|
|
* @throws InvalidArgumentException
|
|
|
|
|
* @throws ModelNotFoundException
|
2022-08-19 19:48:37 +08:00
|
|
|
*/
|
|
|
|
|
public function login(string $nickname = '', string $pwd = '')
|
|
|
|
|
{
|
|
|
|
|
// 支持邮箱或手机登录
|
|
|
|
|
if (filter_var($nickname, FILTER_VALIDATE_EMAIL)) {
|
|
|
|
|
$where[] = ['email', '=', htmlspecialchars(trim($nickname))];
|
|
|
|
|
} else {
|
|
|
|
|
$where[] = ['mobile', '=', htmlspecialchars(trim($nickname))];
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
$user = UserModel::where($where)->find();
|
2022-11-28 19:11:12 +08:00
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
if (!empty($user)) {
|
|
|
|
|
|
|
|
|
|
$uPwd = encryptPwd($pwd, $user['salt']);
|
|
|
|
|
if ($user['pwd'] !== $uPwd) {
|
2022-08-19 19:48:37 +08:00
|
|
|
|
|
|
|
|
$this->setError('用户名或密码错误');
|
2022-12-02 11:16:57 +08:00
|
|
|
UserLog::write($this->getError(), $user['nickname'], $user['id']);
|
2022-08-19 19:48:37 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
if (!$user['status']) {
|
2022-08-19 19:48:37 +08:00
|
|
|
$this->setError('用户异常或未审核,请联系管理员');
|
2022-12-02 11:16:57 +08:00
|
|
|
UserLog::write($this->getError(), $user['nickname'], $user['id']);
|
2022-08-19 19:48:37 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新登录数据
|
2022-12-02 11:16:57 +08:00
|
|
|
$update = [
|
|
|
|
|
'id' => $user['id'],
|
2022-08-19 19:48:37 +08:00
|
|
|
'login_time' => time(),
|
2022-08-23 11:11:42 +08:00
|
|
|
'login_ip' => request()->getRealIp(),
|
2022-12-02 11:16:57 +08:00
|
|
|
'login_count' => $user['login_count'] + 1,
|
2022-08-19 19:48:37 +08:00
|
|
|
];
|
|
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
if (UserModel::update($update)) {
|
|
|
|
|
Event::emit('userLoginSuccess', $user);
|
|
|
|
|
UserLog::write('登录成功', $user['nickname'], $user['id'], 1);
|
|
|
|
|
return $this->responseToken($user);
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->setError('您登录的用户不存在');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 验证是否登录
|
|
|
|
|
* @return bool
|
2022-12-02 11:16:57 +08:00
|
|
|
* @throws DataNotFoundException
|
|
|
|
|
* @throws DbException
|
|
|
|
|
* @throws ModelNotFoundException|InvalidArgumentException
|
2022-08-19 19:48:37 +08:00
|
|
|
*/
|
|
|
|
|
public function isLogin(): bool
|
|
|
|
|
{
|
|
|
|
|
$token = $this->getToken();
|
|
|
|
|
if (!$token) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
// 验证token
|
|
|
|
|
$user = $this->checkToken($token);
|
|
|
|
|
if (isset($user['id'])) {
|
|
|
|
|
$this->userInfo = UserModel::with('group')->find($user['id']);
|
|
|
|
|
if (!empty($this->userInfo)) {
|
|
|
|
|
$this->token = $token;
|
|
|
|
|
$this->user_id = $user['id'];
|
|
|
|
|
$this->refreshUserInfo($token, $this->userInfo);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-12-02 11:16:57 +08:00
|
|
|
* 获取用户信息
|
2022-08-19 19:48:37 +08:00
|
|
|
*/
|
2022-12-02 11:16:57 +08:00
|
|
|
public function getUserInfo()
|
2022-08-19 19:48:37 +08:00
|
|
|
{
|
2022-12-02 11:16:57 +08:00
|
|
|
$token = $this->getToken();
|
|
|
|
|
if (!$token) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取用户信息
|
|
|
|
|
return $this->checkToken($token);
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* 返回前端令牌
|
2022-12-02 11:16:57 +08:00
|
|
|
* @param $user
|
2022-08-19 19:48:37 +08:00
|
|
|
* @param bool $token
|
2022-12-02 11:16:57 +08:00
|
|
|
* @return Response
|
|
|
|
|
* @throws InvalidArgumentException
|
2022-08-19 19:48:37 +08:00
|
|
|
*/
|
2022-12-02 11:16:57 +08:00
|
|
|
public function responseToken($user, bool $token = false): Response
|
2022-08-19 19:48:37 +08:00
|
|
|
{
|
2022-12-02 11:16:57 +08:00
|
|
|
$this->token = $token ? $this->getToken() : $this->buildToken($user['id']);
|
2022-08-19 19:48:37 +08:00
|
|
|
$response = response();
|
2022-12-02 11:16:57 +08:00
|
|
|
$response->cookie('uid', $user['id'], $this->keepTime, '/');
|
|
|
|
|
$response->cookie('token', $this->token, $this->keepTime, '/');
|
|
|
|
|
$response->cookie('nickname', $user['nickname'], $this->keepTime, '/');
|
|
|
|
|
$this->refreshUserInfo($this->token, $user);
|
|
|
|
|
// 执行登录成功事件
|
|
|
|
|
Event::emit("userLoginSuccess", $user);
|
2022-08-19 19:48:37 +08:00
|
|
|
return $response;
|
2022-12-02 11:16:57 +08:00
|
|
|
}
|
2022-08-19 19:48:37 +08:00
|
|
|
|
2022-12-02 11:16:57 +08:00
|
|
|
/**
|
|
|
|
|
* 刷新用户信息
|
|
|
|
|
* @param $token
|
|
|
|
|
* @param $user
|
|
|
|
|
* @return void
|
|
|
|
|
* @throws InvalidArgumentException
|
|
|
|
|
*/
|
|
|
|
|
private function refreshUserInfo($token, $user): void
|
|
|
|
|
{
|
|
|
|
|
Cache::set($token, $user, $this->keepTime);
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 生成token
|
|
|
|
|
* @access protected
|
|
|
|
|
* @param $id
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
protected function buildToken($id): string
|
|
|
|
|
{
|
|
|
|
|
return md5(Random::alpha(16) . $id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取token
|
|
|
|
|
*/
|
|
|
|
|
public function getToken($token = 'token')
|
|
|
|
|
{
|
|
|
|
|
return request()->header($token, input($token, request()->cookie($token)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 校验token
|
|
|
|
|
*/
|
|
|
|
|
public function checkToken($token)
|
|
|
|
|
{
|
2022-12-02 11:16:57 +08:00
|
|
|
return Cache::get($token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 退出登录
|
|
|
|
|
* @return void
|
|
|
|
|
* @throws InvalidArgumentException
|
|
|
|
|
*/
|
|
|
|
|
public function logout()
|
|
|
|
|
{
|
|
|
|
|
Cache::delete($this->token);
|
2022-08-19 19:48:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取最后产生的错误
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function getError(): string
|
|
|
|
|
{
|
|
|
|
|
return $this->_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置错误
|
|
|
|
|
* @param string $error 信息信息
|
2022-11-28 19:11:12 +08:00
|
|
|
* @return void
|
2022-08-19 19:48:37 +08:00
|
|
|
*/
|
2022-11-28 19:11:12 +08:00
|
|
|
protected function setError(string $error): void
|
2022-08-19 19:48:37 +08:00
|
|
|
{
|
|
|
|
|
$this->_error = $error;
|
|
|
|
|
}
|
|
|
|
|
}
|