mirror of
https://gitee.com/wonderful-code/buildadmin
synced 2024-11-21 22:55:36 +00:00
feat:增加Token管理类
This commit is contained in:
parent
c2c4326d7b
commit
84efe593f5
@ -1,9 +1,12 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use bd\Random;
|
||||
use app\common\controller\Backend;
|
||||
use app\common\facade\Token;
|
||||
use think\facade\Db;
|
||||
|
||||
class Index extends Backend
|
||||
{
|
||||
@ -14,16 +17,17 @@ class Index extends Backend
|
||||
|
||||
public function login()
|
||||
{
|
||||
$url = $this->request->get('url', '/admin');
|
||||
$url = $this->request->get('url', '/admin');
|
||||
$token = Random::uuid();
|
||||
// Db::name
|
||||
|
||||
// 检查登录态
|
||||
|
||||
// 检查提交
|
||||
if ($this->request->isPost()) {
|
||||
$username = $this->request->post('username');
|
||||
$password = $this->request->post('password');
|
||||
$username = $this->request->post('username');
|
||||
$password = $this->request->post('password');
|
||||
$keeplogin = $this->request->post('keeplogin');
|
||||
$token = $this->request->post('__token__');
|
||||
|
||||
print_r($username);
|
||||
}
|
||||
|
23
app/common/facade/Token.php
Normal file
23
app/common/facade/Token.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\facade;
|
||||
|
||||
use app\common\library\token\Driver;
|
||||
use think\Facade;
|
||||
|
||||
/**
|
||||
* Token 门面类
|
||||
* @see Driver
|
||||
* @method Driver get(string $token) static 获取 token 的数据
|
||||
* @method Driver set(string $token, string $type, int $user_id, int $expire = 0) static 设置 token
|
||||
* @method Driver check(string $token, string $type, int $user_id) static 检查token是否有效
|
||||
* @method Driver delete(string $token) static 删除一个token
|
||||
* @method Driver clear(string $type, int $user_id) static 清理一个用户的所有token
|
||||
*/
|
||||
class Token extends Facade
|
||||
{
|
||||
protected static function getFacadeClass()
|
||||
{
|
||||
return 'app\common\library\Token';
|
||||
}
|
||||
}
|
91
app/common/library/Token.php
Normal file
91
app/common/library/Token.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\library;
|
||||
|
||||
use app\common\library\token\Driver;
|
||||
use think\helper\Arr;
|
||||
use think\Manager;
|
||||
|
||||
/**
|
||||
* Token 管理类
|
||||
* @see Manager 用来加载驱动
|
||||
* @mixin Driver
|
||||
*/
|
||||
class Token extends Manager
|
||||
{
|
||||
protected $namespace = '\\app\\common\\library\\token\\driver\\';
|
||||
|
||||
/**
|
||||
* 默认驱动
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultDriver()
|
||||
{
|
||||
return $this->getConfig('default');
|
||||
}
|
||||
|
||||
public function getConfig(string $name = null, $default = null)
|
||||
{
|
||||
if (!is_null($name)) {
|
||||
return $this->app->config->get('buildadmin.token.' . $name, $default);
|
||||
}
|
||||
|
||||
return $this->app->config->get('buildadmin.token');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取驱动配置
|
||||
* @param string $store
|
||||
* @param string $name
|
||||
* @param null $default
|
||||
* @return array
|
||||
*/
|
||||
public function getStoreConfig(string $store, string $name = null, $default = null)
|
||||
{
|
||||
if ($config = $this->getConfig("stores.{$store}")) {
|
||||
return Arr::get($config, $name, $default);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException("Store [$store] not found.");
|
||||
}
|
||||
|
||||
protected function resolveType(string $name)
|
||||
{
|
||||
return $this->getStoreConfig($name, 'type', 'mysql');
|
||||
}
|
||||
|
||||
protected function resolveConfig(string $name)
|
||||
{
|
||||
return $this->getStoreConfig($name);
|
||||
}
|
||||
|
||||
public function store(string $name = null)
|
||||
{
|
||||
return $this->driver($name);
|
||||
}
|
||||
|
||||
public function set(string $token, string $type, int $user_id, int $expire = null): bool
|
||||
{
|
||||
return $this->store()->set($token, $type, $user_id, $expire);
|
||||
}
|
||||
|
||||
public function get(string $token): array
|
||||
{
|
||||
return $this->store()->get($token);
|
||||
}
|
||||
|
||||
public function check(string $token, string $type, int $user_id): bool
|
||||
{
|
||||
return $this->store()->check($token, $type, $user_id);
|
||||
}
|
||||
|
||||
public function delete(string $token): bool
|
||||
{
|
||||
return $this->store()->delete($token);
|
||||
}
|
||||
|
||||
public function clear(string $type, int $user_id): bool
|
||||
{
|
||||
return $this->store()->clear($type, $user_id);
|
||||
}
|
||||
}
|
90
app/common/library/token/Driver.php
Normal file
90
app/common/library/token/Driver.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\library\token;
|
||||
|
||||
use think\facade\Config;
|
||||
|
||||
/**
|
||||
* Token 驱动抽象类
|
||||
*/
|
||||
abstract class Driver
|
||||
{
|
||||
/**
|
||||
* @var null 具体驱动的句柄 Mysql|Redis
|
||||
*/
|
||||
protected $handler = null;
|
||||
/**
|
||||
* @var array 配置数据
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* 设置 token
|
||||
* @param string $token Token
|
||||
* @param string $type Type:admin|user
|
||||
* @param int $user_id 用户ID
|
||||
* @param int $expire 过期时间
|
||||
* @return bool
|
||||
*/
|
||||
abstract function set(string $token, string $type, int $user_id, int $expire = 0): bool;
|
||||
|
||||
/**
|
||||
* 获取 token 的数据
|
||||
* @param string $token Token
|
||||
* @return array
|
||||
*/
|
||||
abstract function get(string $token): array;
|
||||
|
||||
/**
|
||||
* 检查token是否有效
|
||||
* @param string $token
|
||||
* @param string $type
|
||||
* @param int $user_id
|
||||
* @return bool
|
||||
*/
|
||||
abstract function check(string $token, string $type, int $user_id): bool;
|
||||
|
||||
/**
|
||||
* 删除一个token
|
||||
* @param string $token
|
||||
* @return bool
|
||||
*/
|
||||
abstract function delete(string $token): bool;
|
||||
|
||||
/**
|
||||
* 清理一个用户的所有token
|
||||
* @param string $type
|
||||
* @param int $user_id
|
||||
* @return bool
|
||||
*/
|
||||
abstract function clear(string $type, int $user_id): bool;
|
||||
|
||||
/**
|
||||
* 返回句柄对象
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function handler()
|
||||
{
|
||||
return $this->handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
* @return string
|
||||
*/
|
||||
protected function getEncryptedToken(string $token): string
|
||||
{
|
||||
$config = Config::get('buildadmin.token');
|
||||
return hash_hmac($config['algo'], $token, $config['key']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $expiretime
|
||||
* @return int
|
||||
*/
|
||||
protected function getExpiredIn(int $expiretime): int
|
||||
{
|
||||
return $expiretime ? max(0, $expiretime - time()) : 365 * 86400;
|
||||
}
|
||||
}
|
83
app/common/library/token/driver/Mysql.php
Normal file
83
app/common/library/token/driver/Mysql.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\library\token\driver;
|
||||
|
||||
use app\common\library\token\Driver;
|
||||
use think\facade\Db;
|
||||
|
||||
/**
|
||||
* @see Driver
|
||||
*/
|
||||
class Mysql extends Driver
|
||||
{
|
||||
/**
|
||||
* 默认配置
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param array $options 参数
|
||||
* @access public
|
||||
*/
|
||||
public function __construct($options = [])
|
||||
{
|
||||
if (!empty($options)) {
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
|
||||
if ($this->options['name']) {
|
||||
$this->handler = Db::connect($this->options['name'])->name($this->options['table']);
|
||||
} else {
|
||||
$this->handler = Db::name($this->options['table']);
|
||||
}
|
||||
}
|
||||
|
||||
public function set(string $token, string $type, int $user_id, int $expire = null): bool
|
||||
{
|
||||
if (is_null($expire)) {
|
||||
$expire = $this->options['expire'];
|
||||
}
|
||||
$expiretime = $expire !== 0 ? time() + $expire : 0;
|
||||
$token = $this->getEncryptedToken($token);
|
||||
$this->handler->insert(['token' => $token, 'type' => $type, 'user_id' => $user_id, 'createtime' => time(), 'expiretime' => $expiretime]);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function get(string $token): array
|
||||
{
|
||||
$data = $this->handler->where('token', $this->getEncryptedToken($token))->find();
|
||||
if ($data) {
|
||||
if (!$data['expiretime'] || $data['expiretime'] > time()) {
|
||||
//返回未加密的token给客户端使用
|
||||
$data['token'] = $token;
|
||||
//返回剩余有效时间
|
||||
$data['expires_in'] = $this->getExpiredIn($data['expiretime']);
|
||||
return $data;
|
||||
} else {
|
||||
self::delete($token);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function check(string $token, string $type, int $user_id): bool
|
||||
{
|
||||
$data = $this->get($token);
|
||||
return $data && $data['type'] == $type && $data['user_id'] == $user_id;
|
||||
}
|
||||
|
||||
public function delete(string $token): bool
|
||||
{
|
||||
$this->handler->where('token', $this->getEncryptedToken($token))->delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function clear(string $type, int $user_id): bool
|
||||
{
|
||||
$this->handler->where('type', $type)->where('user_id', $user_id)->delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
26
app/common/library/token/driver/Redis.php
Normal file
26
app/common/library/token/driver/Redis.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\library\token\driver;
|
||||
|
||||
use app\common\library\token\Driver;
|
||||
|
||||
class Redis
|
||||
{
|
||||
/**
|
||||
* 默认配置
|
||||
* @var array
|
||||
*/
|
||||
protected $options = [];
|
||||
|
||||
public function __construct($options = [])
|
||||
{
|
||||
if (!empty($options)) {
|
||||
$this->options = array_merge($this->options, $options);
|
||||
}
|
||||
|
||||
echo '待完善' . PHP_EOL;
|
||||
echo '---Redis配置信息---' . PHP_EOL;
|
||||
print_r($this->options);
|
||||
}
|
||||
|
||||
}
|
@ -19,4 +19,36 @@ return [
|
||||
'web-install' => 'cd ../web && cnpm install',
|
||||
'web-build' => 'cd ../web && cnpm run build:online',
|
||||
],
|
||||
'token' => [
|
||||
// 默认驱动方式
|
||||
'default' => 'mysql',
|
||||
// 加密key
|
||||
'key' => 'tcbDgmqLVzuAdNH39o0QnhOisvSCFZ7I',
|
||||
// 加密方式
|
||||
'algo' => 'ripemd160',
|
||||
// 驱动
|
||||
'stores' => [
|
||||
'mysql' => [
|
||||
'type' => 'Mysql',
|
||||
// 留空表示使用默认的 Mysql 数据库,也可以填写其他数据库连接配置的`name`
|
||||
'name' => '',
|
||||
// 存储token的表名
|
||||
'table' => 'token',
|
||||
// 默认 token 有效时间
|
||||
'expire' => 2592000,
|
||||
],
|
||||
'redis' => [
|
||||
'type' => 'Redis',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'password' => '',
|
||||
'select' => 0,
|
||||
'timeout' => 0,
|
||||
'expire' => 0,
|
||||
'persistent' => false,
|
||||
'userprefix' => 'up:',
|
||||
'tokenprefix' => 'tp:',
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
23
extend/bd/Random.php
Normal file
23
extend/bd/Random.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace bd;
|
||||
|
||||
class Random
|
||||
{
|
||||
/**
|
||||
* 获取全球唯一标识
|
||||
* @return string
|
||||
*/
|
||||
public static function uuid()
|
||||
{
|
||||
return sprintf(
|
||||
'%04x%04x-%04x-%04x-%04x-',
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0x0fff) | 0x4000,
|
||||
mt_rand(0, 0x3fff) | 0x8000
|
||||
) . substr(md5(uniqid(mt_rand(), true)), 0, 12);
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
import Axios from '/@/utils/axios'
|
||||
|
||||
export function login(params: object) {
|
||||
export function login(params: object, method: 'get'|'post') {
|
||||
return Axios.request({
|
||||
url: '/index.php/admin/index/login',
|
||||
method: 'post',
|
||||
method: method,
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
@ -151,6 +151,8 @@ const rules = reactive({
|
||||
],
|
||||
})
|
||||
|
||||
var token = ''
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
pageBubble.init()
|
||||
@ -163,6 +165,10 @@ onMounted(() => {
|
||||
} else if (form.code === '') {
|
||||
vm.ctx.$refs.code.focus()
|
||||
}
|
||||
|
||||
login({}, 'get').then((res) => {
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
@ -178,7 +184,7 @@ const onSubmit = (formEl: InstanceType<typeof ElForm> | undefined) => {
|
||||
formEl.validate((valid) => {
|
||||
if (valid) {
|
||||
form.loading = true
|
||||
login(form)
|
||||
login(form, 'post')
|
||||
.then((res) => {
|
||||
console.log(res)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user