feat: admin login
This commit is contained in:
21
app/Constants/Admin/UserCode.php
Normal file
21
app/Constants/Admin/UserCode.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Constants\Admin;
|
||||||
|
|
||||||
|
use Hyperf\Constants\AbstractConstants;
|
||||||
|
use Hyperf\Constants\Annotation\Constants;
|
||||||
|
|
||||||
|
#[Constants]
|
||||||
|
class UserCode extends AbstractConstants
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 禁用
|
||||||
|
* @Message("该用户已被禁用")
|
||||||
|
*/
|
||||||
|
const DISABLE = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用
|
||||||
|
*/
|
||||||
|
const ENABLE = 1;
|
||||||
|
}
|
||||||
10
app/Exception/AdminException.php
Normal file
10
app/Exception/AdminException.php
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exception;
|
||||||
|
|
||||||
|
use Hyperf\Server\Exception\ServerException;
|
||||||
|
|
||||||
|
class AdminException extends ServerException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
45
app/Exception/Handler/AdminExceptionHandler.php
Normal file
45
app/Exception/Handler/AdminExceptionHandler.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exception\Handler;
|
||||||
|
|
||||||
|
use App\Exception\AdminException;
|
||||||
|
use App\Lib\AdminReturn;
|
||||||
|
use Hyperf\ExceptionHandler\ExceptionHandler;
|
||||||
|
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class AdminExceptionHandler extends ExceptionHandler
|
||||||
|
{
|
||||||
|
public function __construct(protected AdminReturn $return)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* admin控制器异常处理
|
||||||
|
* @param Throwable $throwable
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function handle(Throwable $throwable, ResponseInterface $response): ResponseInterface
|
||||||
|
{
|
||||||
|
if ($throwable instanceof AdminException) {
|
||||||
|
$result = $this->return->error($throwable->getMessage(),[],$throwable->getCode());
|
||||||
|
|
||||||
|
// 阻止异常冒泡
|
||||||
|
$this->stopPropagation();
|
||||||
|
|
||||||
|
return $response->withHeader("Content-Type", "application/json")
|
||||||
|
->withStatus(200)
|
||||||
|
->withBody(new SwooleStream(json_encode($result, JSON_UNESCAPED_UNICODE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 交给下一个异常处理器
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid(Throwable $throwable): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
63
app/Exception/Handler/ValidationDataExceptionHandler.php
Normal file
63
app/Exception/Handler/ValidationDataExceptionHandler.php
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exception\Handler;
|
||||||
|
|
||||||
|
use App\Lib\AdminReturn;
|
||||||
|
use Hyperf\ExceptionHandler\ExceptionHandler;
|
||||||
|
use Hyperf\HttpServer\Request;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Throwable;
|
||||||
|
use Hyperf\Validation\ValidationException;
|
||||||
|
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||||||
|
|
||||||
|
class ValidationDataExceptionHandler extends ExceptionHandler
|
||||||
|
{
|
||||||
|
public function __construct(protected AdminReturn $adminReturn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证器异常处理
|
||||||
|
* @param Throwable $throwable
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function handle(Throwable $throwable, ResponseInterface $response): ResponseInterface
|
||||||
|
{
|
||||||
|
if ($throwable instanceof ValidationException) {
|
||||||
|
// 格式化输出
|
||||||
|
$request = new Request();
|
||||||
|
$url = $request->path();
|
||||||
|
|
||||||
|
$urlArr = explode('/',$url);
|
||||||
|
|
||||||
|
if ($urlArr[0] == 'admin') {
|
||||||
|
$result = $this->adminReturn->error($throwable->validator->errors()->first());
|
||||||
|
}else{
|
||||||
|
//todo api
|
||||||
|
$result = $this->adminReturn->error($throwable->validator->errors()->first());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 阻止异常冒泡
|
||||||
|
$this->stopPropagation();
|
||||||
|
|
||||||
|
if (!is_array($result)){
|
||||||
|
return $response->withHeader("Content-Type", "application/json")
|
||||||
|
->withStatus(200)
|
||||||
|
->withBody(new SwooleStream($result));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response->withHeader("Content-Type", "application/json")
|
||||||
|
->withStatus(200)
|
||||||
|
->withBody(new SwooleStream(json_encode($result, JSON_UNESCAPED_UNICODE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 交给下一个异常处理器
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid(Throwable $throwable): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
60
app/Extend/SystemUtil.php
Normal file
60
app/Extend/SystemUtil.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Extend;
|
||||||
|
|
||||||
|
use Hyperf\Context\Context;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use function Hyperf\Support\env;
|
||||||
|
|
||||||
|
class SystemUtil
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* prod 1=生产环境 0=开发环境
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
static function checkProEnv()
|
||||||
|
{
|
||||||
|
return Env('APP_ENV') == 'prod';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取客户端 ip
|
||||||
|
* @return mixed|string
|
||||||
|
*/
|
||||||
|
static function getClientIp()
|
||||||
|
{
|
||||||
|
$request = Context::get(ServerRequestInterface::class);
|
||||||
|
|
||||||
|
$ip_addr = $request->getHeaderLine('x-forwarded-for');
|
||||||
|
if (self::verifyIp($ip_addr)) {
|
||||||
|
return $ip_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ip_addr = $request->getHeaderLine('remote-host');
|
||||||
|
if (self::verifyIp($ip_addr)) {
|
||||||
|
return $ip_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ip_addr = $request->getHeaderLine('x-real-ip');
|
||||||
|
if (self::verifyIp($ip_addr)) {
|
||||||
|
return $ip_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ip_addr = $request->getServerParams()['remote_addr'] ?? '0.0.0.0';
|
||||||
|
if (self::verifyIp($ip_addr)) {
|
||||||
|
return $ip_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '0.0.0.0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证ip
|
||||||
|
* @param $realIp
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
static function verifyIp($realIp): mixed
|
||||||
|
{
|
||||||
|
return filter_var($realIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ class AdminReturn
|
|||||||
* @param array $debug
|
* @param array $debug
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function success(string $msg = 'success', array $data = [], int $code = ReturnCode::SUCCESS, array $debug = []): array
|
public function success(string $msg = 'success', array $data = [], int $code = ReturnCode::SUCCESS, array $debug = []): array
|
||||||
{
|
{
|
||||||
$res = [
|
$res = [
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
@@ -34,7 +34,7 @@ class AdminReturn
|
|||||||
* @param array $debug
|
* @param array $debug
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public static function error(string $msg = 'error', array $data = [], int $code = ReturnCode::ERROR, array $debug = []): array
|
public function error(string $msg = 'error', int $code = ReturnCode::ERROR, array $data = [], array $debug = []): array
|
||||||
{
|
{
|
||||||
$res = [
|
$res = [
|
||||||
'code' => $code,
|
'code' => $code,
|
||||||
|
|||||||
42
app/Lib/Crypto/AdminPasswordCrypto.php
Normal file
42
app/Lib/Crypto/AdminPasswordCrypto.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Lib\Crypto;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class AdminPasswordCrypto implements CryptoInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 明文密码
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public string $data = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密盐
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public string $salt = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* admin password 加密
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encrypt(): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return hash("sha256", $this->salt . hash("sha256", $this->salt . $this->data));
|
||||||
|
} catch (Exception) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密 不需要解密
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function decrypt(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
76
app/Lib/Crypto/ApiCrypto.php
Normal file
76
app/Lib/Crypto/ApiCrypto.php
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This lib file is part of item.
|
||||||
|
*
|
||||||
|
* @author ctexthuang
|
||||||
|
* @contact ctexthuang@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Lib\Crypto;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use function Hyperf\Config\config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口加密类
|
||||||
|
*/
|
||||||
|
class ApiCrypto implements CryptoInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 加密数据
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public string $data = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密key
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private string $key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造方法 配置写入
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->key = config('system.api_return_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api加密接口
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encrypt(): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
//设置偏移量
|
||||||
|
$iv = substr(md5($this->data), 0, 16);
|
||||||
|
//使用 openssl 加密数据
|
||||||
|
$encrypted = openssl_encrypt($this->data,'AES-128-CBC',$this->key,OPENSSL_RAW_DATA,$iv);
|
||||||
|
return $iv.'|'.base64_encode($encrypted);
|
||||||
|
} catch (Exception) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api解密接口
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function decrypt(): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$array = explode('|',$this->data);
|
||||||
|
//获取偏移量
|
||||||
|
$iv = $array[0];
|
||||||
|
//获取加密数据
|
||||||
|
$encrypted = base64_decode($array[1]);
|
||||||
|
//使用 openssl 解密数据 并返回
|
||||||
|
return openssl_decrypt($encrypted, 'AES-128-CBC',$this->key,OPENSSL_RAW_DATA,$iv);
|
||||||
|
} catch (Exception) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
57
app/Lib/Crypto/CryptoFactory.php
Normal file
57
app/Lib/Crypto/CryptoFactory.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This service file is part of item.
|
||||||
|
*
|
||||||
|
* @author ctexthuang
|
||||||
|
* @contact ctexthuang@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Lib\Crypto;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密工厂
|
||||||
|
*/
|
||||||
|
class CryptoFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 加密类主体
|
||||||
|
* @var CryptoInterface
|
||||||
|
*/
|
||||||
|
protected CryptoInterface $cryptoInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密工厂
|
||||||
|
* @param string $type
|
||||||
|
* @param string $dataStr
|
||||||
|
* @param string $key
|
||||||
|
* @return ApiCrypto|CryptoInterface|JwtCrypto
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function cryptoClass(string $type, string $dataStr, string $key = ''): JwtCrypto|CryptoInterface|ApiCrypto
|
||||||
|
{
|
||||||
|
switch ($type) {
|
||||||
|
case 'api':
|
||||||
|
$apiCrypto = new ApiCrypto();
|
||||||
|
$this->cryptoInterface = $apiCrypto;
|
||||||
|
break;
|
||||||
|
case 'jwt':
|
||||||
|
$jwtCrypto = new JwtCrypto();
|
||||||
|
$this->cryptoInterface = $jwtCrypto;
|
||||||
|
break;
|
||||||
|
case 'admin-password':
|
||||||
|
$adminCrypto = new AdminPasswordCrypto();
|
||||||
|
$this->cryptoInterface = $adminCrypto;
|
||||||
|
$this->cryptoInterface->salt = $key;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception('The encryption algorithm does not exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cryptoInterface->data = $dataStr;
|
||||||
|
return $this->cryptoInterface;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/Lib/Crypto/CryptoInterface.php
Normal file
20
app/Lib/Crypto/CryptoInterface.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This lib file is part of item.
|
||||||
|
*
|
||||||
|
* @author ctexthuang
|
||||||
|
* @contact ctexthuang@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Lib\Crypto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密类接口
|
||||||
|
*/
|
||||||
|
interface CryptoInterface
|
||||||
|
{
|
||||||
|
public function encrypt();
|
||||||
|
public function decrypt();
|
||||||
|
}
|
||||||
80
app/Lib/Crypto/JwtCrypto.php
Normal file
80
app/Lib/Crypto/JwtCrypto.php
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This lib file is part of item.
|
||||||
|
*
|
||||||
|
* @author ctexthuang
|
||||||
|
* @contact ctexthuang@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Lib\Crypto;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Firebase\JWT\JWT;
|
||||||
|
use Firebase\JWT\Key;
|
||||||
|
use function Hyperf\Config\config;
|
||||||
|
|
||||||
|
class JwtCrypto implements CryptoInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 加密数据
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public string $data = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密 key
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private string $key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密过期时间
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private int $expire;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数 获取配置
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->key = config('system.jwt_key');
|
||||||
|
$this->expire = (int)config('system.jwt_expire');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jwt 加密
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function encrypt(): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$time = time();
|
||||||
|
$payload = [
|
||||||
|
'iat' => $time, //签发时间
|
||||||
|
'nbf' => $time, //(Not Before):某个时间点后才能访问,比如设置time+30,表示当前时间30秒后才能使用
|
||||||
|
'exp' => $time + $this->expire,
|
||||||
|
'data' => json_decode($this->data,true),
|
||||||
|
];
|
||||||
|
|
||||||
|
return JWT::encode($payload, $this->key,'HS256');
|
||||||
|
} catch (Exception) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jwt 解密
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function decrypt(): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return (array)JWT::decode($this->data, new Key($this->key, 'HS256'));
|
||||||
|
} catch (Exception) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
app/Model/AdminUser.php
Normal file
56
app/Model/AdminUser.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Model;
|
||||||
|
|
||||||
|
use Hyperf\Database\Model\Builder;
|
||||||
|
use Hyperf\DbConnection\Model\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $username
|
||||||
|
* @property string $password
|
||||||
|
* @property string $salt
|
||||||
|
* @property int $avatar
|
||||||
|
* @property string $chinese_name
|
||||||
|
* @property string $mobile
|
||||||
|
* @property int $status
|
||||||
|
* @property string $last_login_ip
|
||||||
|
* @property string $last_login_time
|
||||||
|
* @property int $is_del
|
||||||
|
* @property int $role_id
|
||||||
|
* @property string $create_time
|
||||||
|
*/
|
||||||
|
class AdminUser extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*/
|
||||||
|
protected ?string $table = 'admin_user';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*/
|
||||||
|
protected array $fillable = [];
|
||||||
|
|
||||||
|
protected array $guarded = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast to native types.
|
||||||
|
*/
|
||||||
|
protected array $casts = ['id' => 'integer', 'avatar' => 'integer', 'status' => 'integer', 'is_del' => 'integer', 'role_id' => 'integer'];
|
||||||
|
|
||||||
|
const CREATED_AT = 'create_time';
|
||||||
|
|
||||||
|
const UPDATED_AT = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $account
|
||||||
|
* @return Builder|\Hyperf\Database\Model\Model|null
|
||||||
|
*/
|
||||||
|
public function getAdminInfoByAccount($account): \Hyperf\Database\Model\Model|Builder|null
|
||||||
|
{
|
||||||
|
return $this->where('username', $account)->where('is_del',1)->first();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,10 +10,27 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Service\Admin;
|
namespace App\Service\Admin;
|
||||||
|
|
||||||
|
use App\Lib\AdminReturn;
|
||||||
use Hyperf\Context\Context;
|
use Hyperf\Context\Context;
|
||||||
|
use Hyperf\Di\Annotation\Inject;
|
||||||
|
use Hyperf\HttpServer\Contract\RequestInterface;
|
||||||
|
|
||||||
abstract class BaseService
|
abstract class BaseService
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 请求对象
|
||||||
|
* @var RequestInterface
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected RequestInterface $request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用返回对象
|
||||||
|
* @var AdminReturn $return
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected AdminReturn $return;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 管理员id
|
* 管理员id
|
||||||
* @var int $adminId
|
* @var int $adminId
|
||||||
|
|||||||
@@ -10,13 +10,68 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Service\Admin\User;
|
namespace App\Service\Admin\User;
|
||||||
|
|
||||||
|
use App\Constants\Admin\UserCode;
|
||||||
|
use App\Constants\AdminCode;
|
||||||
|
use App\Exception\AdminException;
|
||||||
|
use App\Extend\SystemUtil;
|
||||||
use App\Lib\AdminReturn;
|
use App\Lib\AdminReturn;
|
||||||
|
use App\Lib\Crypto\CryptoFactory;
|
||||||
|
use App\Model\AdminUser;
|
||||||
use App\Service\Admin\BaseService;
|
use App\Service\Admin\BaseService;
|
||||||
|
use App\Service\Common\AppMakeService;
|
||||||
|
use Exception;
|
||||||
|
use Hyperf\Di\Annotation\Inject;
|
||||||
|
|
||||||
class LoginService extends BaseService
|
class LoginService extends BaseService
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入管理员模型
|
||||||
|
* @var AdminUser $adminUserModel
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected AdminUser $adminUserModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入加密工厂
|
||||||
|
* @var CryptoFactory $cryptoFactory
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected CryptoFactory $cryptoFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台登录
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public function handle(): array
|
public function handle(): array
|
||||||
{
|
{
|
||||||
return AdminReturn::success();
|
$userInfo = $this->adminUserModel->getAdminInfoByAccount($this->request->input('account'));
|
||||||
|
if (!$userInfo) throw new AdminException('账号不存在');
|
||||||
|
|
||||||
|
if ($userInfo->status == UserCode::DISABLE) throw new AdminException(UserCode::getMessage($userInfo->status),AdminCode::LOGIN_ERROR);
|
||||||
|
|
||||||
|
if ($this->cryptoFactory->cryptoClass('admin-password',$this->request->input('password'),$userInfo->salt) != $userInfo->password) throw new AdminException('密码错误!');
|
||||||
|
|
||||||
|
$userInfo->last_login_time = date('Y-m-d H:i:s');
|
||||||
|
$userInfo->last_login_ip = SystemUtil::getClientIp();
|
||||||
|
$userInfo->save();
|
||||||
|
|
||||||
|
if (!$userInfo->save()) throw new AdminException('登录失败');
|
||||||
|
|
||||||
|
$token = $this->cryptoFactory->cryptoClass('jwt',json_encode([
|
||||||
|
'id' => $userInfo->id,
|
||||||
|
'role' => $userInfo->role_id,
|
||||||
|
]))->encrypt();
|
||||||
|
|
||||||
|
return $this->return->success('success',[
|
||||||
|
'token' => $token,
|
||||||
|
'info' => [
|
||||||
|
'admin_id' => $userInfo->id,
|
||||||
|
'avatar' => $userInfo->avatar,
|
||||||
|
'name' => $userInfo->chinese_name,
|
||||||
|
'role_id' => $userInfo->role_id,
|
||||||
|
]
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
46
app/Service/Common/AppMakeService.php
Normal file
46
app/Service/Common/AppMakeService.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This service file is part of item.
|
||||||
|
*
|
||||||
|
* @author ctexthuang
|
||||||
|
* @contact ctexthuang@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service\Common;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Hyperf\Context\Context;
|
||||||
|
|
||||||
|
class AppMakeService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 生成类对象
|
||||||
|
* @param $className
|
||||||
|
* @return mixed
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static function make($className): mixed
|
||||||
|
{
|
||||||
|
if (!class_exists($className)) throw new Exception('The instantiated class does not exist');
|
||||||
|
|
||||||
|
$array = Context::get('obj');
|
||||||
|
if (!isset($array[$className])) {
|
||||||
|
$array = $array ?? [];
|
||||||
|
$array[$className] = new $className;
|
||||||
|
Context::set('obj', $array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $array[$className];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对象类
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public static function getObj(): mixed
|
||||||
|
{
|
||||||
|
return Context::get('obj');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@ return [
|
|||||||
'handler' => [
|
'handler' => [
|
||||||
'http' => [
|
'http' => [
|
||||||
Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
|
Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
|
||||||
|
App\Exception\Handler\AdminExceptionHandler::class,
|
||||||
|
App\Exception\Handler\ValidationDataExceptionHandler::class,
|
||||||
App\Exception\Handler\AppExceptionHandler::class,
|
App\Exception\Handler\AppExceptionHandler::class,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|||||||
20
config/autoload/system.php
Normal file
20
config/autoload/system.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This config file is part of item.
|
||||||
|
*
|
||||||
|
* @author ctexthuang
|
||||||
|
* @contact ctexthuang@qq.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use function Hyperf\Support\env;
|
||||||
|
|
||||||
|
return [
|
||||||
|
// api 返回加密/解密 key
|
||||||
|
'api_return_key' => env('API_RETURN_KEY','hhl@shenzhen'),
|
||||||
|
// jwt 加密 key
|
||||||
|
'jwt_key' => env('JWT_KEY','hhl@shenzhen'),
|
||||||
|
// jwt 过期时间
|
||||||
|
'jwt_expire' => env('JWT_EXPIRE',86400 * 30),
|
||||||
|
];
|
||||||
25
sync/database/admin.sql
Normal file
25
sync/database/admin.sql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Server Type : MySQL
|
||||||
|
*/
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- 后台用户表
|
||||||
|
DROP TABLE IF EXISTS `app_admin_user`;
|
||||||
|
CREATE TABLE `app_admin_user` (
|
||||||
|
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`username` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户名',
|
||||||
|
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户密码',
|
||||||
|
`salt` varchar(6) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '盐值',
|
||||||
|
`avatar` int NOT NULL DEFAULT 0 COMMENT '用户头像',
|
||||||
|
`chinese_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '中文名',
|
||||||
|
`mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '手机号',
|
||||||
|
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户状态 1 正常 2 禁用',
|
||||||
|
`last_login_ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '最后登录IP',
|
||||||
|
`last_login_time` datetime NOT NULL COMMENT '最后登录时间',
|
||||||
|
`is_del` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户状态 1 正常 2 删除 涉及到后台操作日志表',
|
||||||
|
`role_id` tinyint(1) NOT NULL DEFAULT '0' COMMENT '角色',
|
||||||
|
`create_time` datetime NOT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='后台用户表';
|
||||||
Reference in New Issue
Block a user