[接口]鉴权authToken用户登录login-注册register-退出logout, 并将用户信息保存到redis中
This commit is contained in:
@@ -7,8 +7,8 @@ DB_USER = root
|
||||
DB_PASSWORD = 123456
|
||||
DB_PREFIX =
|
||||
|
||||
# 缓存方式,支持file|redis
|
||||
CACHE_MODE = file
|
||||
# 缓存方式,支持file|redis(API 用户登录缓存需使用 redis)
|
||||
CACHE_MODE = redis
|
||||
|
||||
# Redis配置
|
||||
REDIS_HOST = 127.0.0.1
|
||||
@@ -16,6 +16,12 @@ REDIS_PORT = 6379
|
||||
REDIS_PASSWORD = ''
|
||||
REDIS_DB = 0
|
||||
|
||||
# API 鉴权与用户(可选,不填则用默认值)
|
||||
# API_AUTH_TOKEN_EXP = 86400
|
||||
# API_USER_TOKEN_EXP = 604800
|
||||
# API_USER_CACHE_EXPIRE = 604800
|
||||
# API_USER_ENCRYPT_KEY = dafuweng_api_user_cache_key_32
|
||||
|
||||
# 验证码配置,支持cache|session
|
||||
CAPTCHA_MODE = cache
|
||||
LOGIN_CAPTCHA_ENABLE = false
|
||||
|
||||
114
server/app/api/cache/UserCache.php
vendored
Normal file
114
server/app/api/cache/UserCache.php
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\cache;
|
||||
|
||||
use support\think\Cache;
|
||||
|
||||
/**
|
||||
* API 用户信息 Redis 缓存
|
||||
* key = base64(user_id),value = 加密后的用户信息 JSON
|
||||
*/
|
||||
class UserCache
|
||||
{
|
||||
private static function prefix(): string
|
||||
{
|
||||
return config('api.user_cache_prefix', 'api:user:');
|
||||
}
|
||||
|
||||
private static function expire(): int
|
||||
{
|
||||
return (int) config('api.user_cache_expire', 604800);
|
||||
}
|
||||
|
||||
private static function encryptKey(): string
|
||||
{
|
||||
$key = config('api.user_encrypt_key', 'dafuweng_api_user_cache_key_32');
|
||||
return str_pad($key, 32, '0', STR_PAD_RIGHT);
|
||||
}
|
||||
|
||||
/** 加密 */
|
||||
public static function encrypt(string $data): string
|
||||
{
|
||||
$key = self::encryptKey();
|
||||
$iv = substr(md5($key), 0, 16);
|
||||
return base64_encode(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv));
|
||||
}
|
||||
|
||||
/** 解密 */
|
||||
public static function decrypt(string $data): string
|
||||
{
|
||||
$key = self::encryptKey();
|
||||
$iv = substr(md5($key), 0, 16);
|
||||
$dec = openssl_decrypt(base64_decode($data, true), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
|
||||
return $dec !== false ? $dec : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入用户信息到 Redis
|
||||
* @param int $userId
|
||||
* @param array $userInfo 从数据库读取的用户信息(可含敏感字段,会加密存储)
|
||||
*/
|
||||
public static function setUser(int $userId, array $userInfo): bool
|
||||
{
|
||||
$key = self::prefix() . base64_encode((string) $userId);
|
||||
$value = self::encrypt(json_encode($userInfo));
|
||||
return Cache::set($key, $value, self::expire());
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Redis 读取用户信息
|
||||
* @return array 解密后的用户信息,不存在或失败返回空数组
|
||||
*/
|
||||
public static function getUser(int $userId): array
|
||||
{
|
||||
$key = self::prefix() . base64_encode((string) $userId);
|
||||
$value = Cache::get($key);
|
||||
if ($value === null || $value === '') {
|
||||
return [];
|
||||
}
|
||||
$dec = self::decrypt($value);
|
||||
if ($dec === '') {
|
||||
return [];
|
||||
}
|
||||
$data = json_decode($dec, true);
|
||||
return is_array($data) ? $data : [];
|
||||
}
|
||||
|
||||
/** 删除用户缓存 */
|
||||
public static function deleteUser(int $userId): bool
|
||||
{
|
||||
$key = self::prefix() . base64_encode((string) $userId);
|
||||
return Cache::delete($key);
|
||||
}
|
||||
|
||||
/** user-token 黑名单前缀(退出登录后使 token 失效) */
|
||||
private static function blacklistPrefix(): string
|
||||
{
|
||||
return config('api.user_cache_prefix', 'api:user:') . 'token_blacklist:';
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 user-token 加入黑名单(退出登录)
|
||||
* @param string $token 完整 token 字符串
|
||||
* @param int $ttl 黑名单过期时间(秒),建议为 token 剩余有效期
|
||||
*/
|
||||
public static function addTokenToBlacklist(string $token, int $ttl = 86400): bool
|
||||
{
|
||||
if ($ttl <= 0) {
|
||||
return true;
|
||||
}
|
||||
$key = self::blacklistPrefix() . md5($token);
|
||||
return Cache::set($key, '1', $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 user-token 是否在黑名单中(已退出)
|
||||
*/
|
||||
public static function isTokenBlacklisted(string $token): bool
|
||||
{
|
||||
$key = self::blacklistPrefix() . md5($token);
|
||||
$val = Cache::get($key);
|
||||
return $val !== null && $val !== '';
|
||||
}
|
||||
}
|
||||
35
server/app/api/controller/AuthTokenController.php
Normal file
35
server/app/api/controller/AuthTokenController.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use Tinywan\Jwt\JwtToken;
|
||||
use plugin\saiadmin\basic\OpenController;
|
||||
|
||||
/**
|
||||
* API 鉴权 Token 接口
|
||||
* 后续所有 /api 接口调用均需在请求头携带此接口返回的 auth-token
|
||||
*/
|
||||
class AuthTokenController extends OpenController
|
||||
{
|
||||
/**
|
||||
* 获取 auth-token
|
||||
* GET 或 POST /api/authToken
|
||||
*/
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$exp = config('api.auth_token_exp', 86400);
|
||||
$tokenResult = JwtToken::generateToken([
|
||||
'id' => 0,
|
||||
'plat' => 'api',
|
||||
'access_exp' => $exp,
|
||||
]);
|
||||
|
||||
return $this->success([
|
||||
'auth-token' => $tokenResult['access_token'],
|
||||
'expires_in' => $tokenResult['expires_in'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
83
server/app/api/controller/UserController.php
Normal file
83
server/app/api/controller/UserController.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use app\api\logic\UserLogic;
|
||||
use plugin\saiadmin\basic\OpenController;
|
||||
|
||||
/**
|
||||
* API 用户登录/注册
|
||||
* 需先携带 auth-token,登录/注册成功后返回 user-token 与用户信息,用户信息已写入 Redis(key=base64(user_id),value=加密)
|
||||
*/
|
||||
class UserController extends OpenController
|
||||
{
|
||||
/**
|
||||
* 登录
|
||||
* POST /api/user/login
|
||||
* body: phone (+60), password
|
||||
*/
|
||||
public function login(Request $request): Response
|
||||
{
|
||||
$phone = $request->post('phone', '');
|
||||
$password = $request->post('password', '');
|
||||
if ($phone === '' || $password === '') {
|
||||
return $this->fail('请填写手机号和密码');
|
||||
}
|
||||
$logic = new UserLogic();
|
||||
$data = $logic->login($phone, $password);
|
||||
return $this->success([
|
||||
'user' => $data['user'],
|
||||
'user-token' => $data['user-token'],
|
||||
'user_id' => $data['user_id'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册
|
||||
* POST /api/user/register
|
||||
* body: phone (+60), password, nickname(可选)
|
||||
*/
|
||||
public function register(Request $request): Response
|
||||
{
|
||||
$phone = $request->post('phone', '');
|
||||
$password = $request->post('password', '');
|
||||
$nickname = $request->post('nickname');
|
||||
if ($phone === '' || $password === '') {
|
||||
return $this->fail('请填写手机号和密码');
|
||||
}
|
||||
$logic = new UserLogic();
|
||||
$data = $logic->register($phone, $password, $nickname ? (string) $nickname : null);
|
||||
return $this->success([
|
||||
'user' => $data['user'],
|
||||
'user-token' => $data['user-token'],
|
||||
'user_id' => $data['user_id'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
* POST /api/user/logout
|
||||
* header: user-token(或 Authorization: Bearer <user-token>)
|
||||
* 将当前 user-token 加入黑名单,之后该 token 无法再用于获取 user_id
|
||||
*/
|
||||
public function logout(Request $request): Response
|
||||
{
|
||||
$token = $request->header('user-token');
|
||||
if (empty($token)) {
|
||||
$auth = $request->header('authorization');
|
||||
if ($auth && stripos($auth, 'Bearer ') === 0) {
|
||||
$token = trim(substr($auth, 7));
|
||||
}
|
||||
}
|
||||
if (empty($token)) {
|
||||
return $this->fail('请携带 user-token');
|
||||
}
|
||||
if (UserLogic::logout($token)) {
|
||||
return $this->success('已退出登录');
|
||||
}
|
||||
return $this->fail('退出失败或 token 已失效');
|
||||
}
|
||||
}
|
||||
180
server/app/api/logic/UserLogic.php
Normal file
180
server/app/api/logic/UserLogic.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\logic;
|
||||
|
||||
use app\dice\model\player\DicePlayer;
|
||||
use app\api\cache\UserCache;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use Tinywan\Jwt\JwtToken;
|
||||
|
||||
/**
|
||||
* API 用户登录/注册逻辑(基于 DicePlayer 表)
|
||||
* 手机号格式限制:+60(马来西亚)
|
||||
*/
|
||||
class UserLogic
|
||||
{
|
||||
/** 手机号正则:+60 开头,后跟 9–10 位数字(马来西亚) */
|
||||
private const PHONE_REGEX = '/^\+60\d{9,10}$/';
|
||||
|
||||
/** 与 DicePlayerLogic 保持一致的密码盐,用于登录校验与注册写入 */
|
||||
private const PASSWORD_SALT = 'dice_player_salt_2024';
|
||||
|
||||
/** 状态:正常 */
|
||||
private const STATUS_NORMAL = 1;
|
||||
|
||||
/**
|
||||
* 手机号格式校验:+60 开头
|
||||
*/
|
||||
public static function validatePhone(string $phone): void
|
||||
{
|
||||
if (!preg_match(self::PHONE_REGEX, $phone)) {
|
||||
throw new ApiException('手机号格式错误,仅支持 +60 开头的马来西亚号码(如 +60123456789)');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录:手机号 + 密码,返回用户信息与 user-token,并写入 Redis 缓存
|
||||
*/
|
||||
public function login(string $phone, string $password): array
|
||||
{
|
||||
self::validatePhone($phone);
|
||||
|
||||
$user = DicePlayer::where('phone', $phone)->find();
|
||||
if (!$user) {
|
||||
throw new ApiException('手机号未注册');
|
||||
}
|
||||
if ((int) $user->status !== self::STATUS_NORMAL) {
|
||||
throw new ApiException('账号已被禁用');
|
||||
}
|
||||
$hashed = $this->hashPassword($password);
|
||||
if ($user->password !== $hashed) {
|
||||
throw new ApiException('密码错误');
|
||||
}
|
||||
|
||||
$userArr = $user->hidden(['password'])->toArray();
|
||||
UserCache::setUser((int) $user->id, $userArr);
|
||||
|
||||
$userToken = $this->generateUserToken((int) $user->id);
|
||||
return [
|
||||
'user' => $userArr,
|
||||
'user-token' => $userToken,
|
||||
'user_id' => (int) $user->id,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册:手机号 + 密码(+60),创建玩家并返回用户信息与 user-token,写入 Redis
|
||||
*/
|
||||
public function register(string $phone, string $password, ?string $nickname = null): array
|
||||
{
|
||||
self::validatePhone($phone);
|
||||
|
||||
if (strlen($password) < 6) {
|
||||
throw new ApiException('密码至少 6 位');
|
||||
}
|
||||
|
||||
$exists = DicePlayer::where('phone', $phone)->find();
|
||||
if ($exists) {
|
||||
throw new ApiException('该手机号已注册');
|
||||
}
|
||||
|
||||
$user = new DicePlayer();
|
||||
$user->phone = $phone;
|
||||
$user->username = $phone;
|
||||
if ($nickname !== null && $nickname !== '') {
|
||||
$user->name = $nickname;
|
||||
}
|
||||
// name 未传时由 DicePlayer::onBeforeInsert 默认设为 uid
|
||||
$user->password = $this->hashPassword($password);
|
||||
$user->status = self::STATUS_NORMAL;
|
||||
$user->save();
|
||||
|
||||
$userArr = $user->hidden(['password'])->toArray();
|
||||
UserCache::setUser((int) $user->id, $userArr);
|
||||
|
||||
$userToken = $this->generateUserToken((int) $user->id);
|
||||
return [
|
||||
'user' => $userArr,
|
||||
'user-token' => $userToken,
|
||||
'user_id' => (int) $user->id,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 与 DicePlayerLogic 一致的密码加密:md5(salt . password)
|
||||
*/
|
||||
private function hashPassword(string $password): string
|
||||
{
|
||||
return md5(self::PASSWORD_SALT . $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 user-token(JWT,plat=api_user,id=user_id)
|
||||
*/
|
||||
private function generateUserToken(int $userId): string
|
||||
{
|
||||
$exp = config('api.user_token_exp', 604800);
|
||||
$result = JwtToken::generateToken([
|
||||
'id' => $userId,
|
||||
'plat' => 'api_user',
|
||||
'access_exp' => $exp,
|
||||
]);
|
||||
return $result['access_token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 user-token 获取 user_id(不写缓存,仅解析 JWT)
|
||||
* 若 token 已通过退出接口加入黑名单,返回 null
|
||||
*/
|
||||
public static function getUserIdFromToken(string $userToken): ?int
|
||||
{
|
||||
if (UserCache::isTokenBlacklisted($userToken)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$decoded = JwtToken::verify(1, $userToken);
|
||||
$extend = $decoded['extend'] ?? [];
|
||||
if (($extend['plat'] ?? '') !== 'api_user') {
|
||||
return null;
|
||||
}
|
||||
$id = $extend['id'] ?? null;
|
||||
return $id !== null ? (int) $id : null;
|
||||
} catch (\Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录:将当前 user-token 加入黑名单,使该 token 失效
|
||||
*/
|
||||
public static function logout(string $userToken): bool
|
||||
{
|
||||
try {
|
||||
$decoded = JwtToken::verify(1, $userToken);
|
||||
$exp = (int) ($decoded['exp'] ?? 0);
|
||||
$ttl = $exp > time() ? $exp - time() : 86400;
|
||||
return UserCache::addTokenToBlacklist($userToken, $ttl);
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Redis 获取用户信息(key = base64(user_id)),未命中则查 DicePlayer 并回写缓存
|
||||
*/
|
||||
public static function getCachedUser(int $userId): array
|
||||
{
|
||||
$cached = UserCache::getUser($userId);
|
||||
if (!empty($cached)) {
|
||||
return $cached;
|
||||
}
|
||||
$user = DicePlayer::find($userId);
|
||||
if (!$user) {
|
||||
return [];
|
||||
}
|
||||
$arr = $user->hidden(['password'])->toArray();
|
||||
UserCache::setUser($userId, $arr);
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
74
server/app/api/middleware/CheckApiAuthMiddleware.php
Normal file
74
server/app/api/middleware/CheckApiAuthMiddleware.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\middleware;
|
||||
|
||||
use support\Log;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
use Tinywan\Jwt\JwtToken;
|
||||
use Tinywan\Jwt\Exception\JwtTokenException;
|
||||
use Tinywan\Jwt\Exception\JwtTokenExpiredException;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
|
||||
/**
|
||||
* API 鉴权中间件
|
||||
* 校验请求头 auth-token(或 Authorization: Bearer xxx),白名单路径不校验
|
||||
*/
|
||||
class CheckApiAuthMiddleware implements MiddlewareInterface
|
||||
{
|
||||
/** 不需要 auth-token 的路径(仅获取 token 的接口) */
|
||||
private const WHITELIST = [
|
||||
'api/authToken',
|
||||
];
|
||||
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$path = trim($request->path(), '/');
|
||||
if ($this->isWhitelist($path)) {
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
$token = $request->header('auth-token');
|
||||
if (empty($token)) {
|
||||
$auth = $request->header('authorization');
|
||||
if ($auth && stripos($auth, 'Bearer ') === 0) {
|
||||
$token = trim(substr($auth, 7));
|
||||
}
|
||||
}
|
||||
if (empty($token)) {
|
||||
throw new ApiException('缺少 auth-token,请先调用 /api/authToken 获取', 401);
|
||||
}
|
||||
|
||||
try {
|
||||
// ACCESS_TOKEN = 1(JwtToken 内部私有常量)
|
||||
$decoded = JwtToken::verify(1, $token);
|
||||
$extend = $decoded['extend'] ?? [];
|
||||
if (($extend['plat'] ?? '') !== 'api') {
|
||||
throw new ApiException('auth-token 无效', 401);
|
||||
}
|
||||
} catch (JwtTokenExpiredException $e) {
|
||||
Log::error('code=401, auth-token 已过期,请重新获取, 报错信息'. $e);
|
||||
throw new ApiException('auth-token 已过期,请重新获取', 401);
|
||||
} catch (JwtTokenException $e) {
|
||||
Log::error('code=401, message=auth-token 无效, 报错信息'. $e);
|
||||
throw new ApiException($e->getMessage() ?: 'auth-token 无效', 401);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('code=401, message=auth-token 校验失败, 报错信息'. $e);
|
||||
throw new ApiException('auth-token 校验失败', 401);
|
||||
}
|
||||
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
private function isWhitelist(string $path): bool
|
||||
{
|
||||
foreach (self::WHITELIST as $prefix) {
|
||||
if ($path === $prefix || str_starts_with($path, $prefix . '/')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
namespace app\dice\model\player;
|
||||
|
||||
use plugin\saiadmin\basic\think\BaseModel;
|
||||
use app\dice\model\lottery_config\DiceLotteryConfig;
|
||||
|
||||
/**
|
||||
* 大富翁-玩家模型
|
||||
@@ -16,6 +17,7 @@ use plugin\saiadmin\basic\think\BaseModel;
|
||||
* @property $id ID
|
||||
* @property $username 用户名
|
||||
* @property $phone 手机
|
||||
* @property $uid uid
|
||||
* @property $name 昵称
|
||||
* @property $password 密码
|
||||
* @property $status 状态
|
||||
@@ -47,6 +49,68 @@ class DicePlayer extends BaseModel
|
||||
*/
|
||||
protected $table = 'dice_player';
|
||||
|
||||
/**
|
||||
* 新增前:生成唯一 uid,昵称 name 默认使用 uid
|
||||
* 用 try-catch 避免表尚未含 uid 时 getAttr/getData 抛 InvalidArgumentException
|
||||
*/
|
||||
public static function onBeforeInsert($model): void
|
||||
{
|
||||
parent::onBeforeInsert($model);
|
||||
try {
|
||||
$uid = $model->getAttr('uid');
|
||||
} catch (\Throwable $e) {
|
||||
$uid = null;
|
||||
}
|
||||
if ($uid === null || $uid === '') {
|
||||
$uid = self::generateUid();
|
||||
$model->setAttr('uid', $uid);
|
||||
}
|
||||
try {
|
||||
$name = $model->getAttr('name');
|
||||
} catch (\Throwable $e) {
|
||||
$name = null;
|
||||
}
|
||||
if ($name === null || $name === '') {
|
||||
$model->setAttr('name', $uid);
|
||||
}
|
||||
// 彩金池权重默认取 type=0 的奖池配置
|
||||
self::setDefaultWeightsFromLotteryConfig($model);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 DiceLotteryConfig type=0 取 t1_wight~t5_wight 作为玩家未设置时的默认值
|
||||
*/
|
||||
protected static function setDefaultWeightsFromLotteryConfig(DicePlayer $model): void
|
||||
{
|
||||
$config = DiceLotteryConfig::where('type', 0)->find();
|
||||
if (!$config) {
|
||||
return;
|
||||
}
|
||||
$fields = ['t1_wight', 't2_wight', 't3_wight', 't4_wight', 't5_wight'];
|
||||
foreach ($fields as $field) {
|
||||
try {
|
||||
$val = $model->getAttr($field);
|
||||
} catch (\Throwable $e) {
|
||||
$val = null;
|
||||
}
|
||||
if ($val === null || $val === '') {
|
||||
try {
|
||||
$model->setAttr($field, $config->getAttr($field));
|
||||
} catch (\Throwable $e) {
|
||||
// 忽略字段不存在
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一标识 uid(12 位十六进制)
|
||||
*/
|
||||
public static function generateUid(): string
|
||||
{
|
||||
return strtoupper(substr(bin2hex(random_bytes(6)), 0, 12));
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户名 搜索
|
||||
*/
|
||||
|
||||
16
server/config/api.php
Normal file
16
server/config/api.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* API 鉴权与用户相关配置
|
||||
*/
|
||||
return [
|
||||
// auth-token 有效期(秒),默认 24 小时
|
||||
'auth_token_exp' => (int) env('API_AUTH_TOKEN_EXP', 86400),
|
||||
// user-token 有效期(秒),默认 7 天
|
||||
'user_token_exp' => (int) env('API_USER_TOKEN_EXP', 604800),
|
||||
// 用户信息 Redis 缓存过期时间(秒),默认 7 天
|
||||
'user_cache_expire' => (int) env('API_USER_CACHE_EXPIRE', 604800),
|
||||
// 用户缓存 Redis key 前缀
|
||||
'user_cache_prefix' => env('API_USER_CACHE_PREFIX', 'api:user:'),
|
||||
// 用户信息加密密钥(用于 Redis 中 value 的加密),建议 32 位
|
||||
'user_encrypt_key' => env('API_USER_ENCRYPT_KEY', 'dafuweng_api_user_cache_key_32'),
|
||||
];
|
||||
@@ -13,9 +13,15 @@
|
||||
*/
|
||||
|
||||
use Webman\Route;
|
||||
|
||||
|
||||
|
||||
use app\api\middleware\CheckApiAuthMiddleware;
|
||||
|
||||
// API 路由:需先调用 /api/authToken 获取 auth-token,请求时携带 header: auth-token 或 Authorization: Bearer <token>
|
||||
Route::group('/api', function () {
|
||||
Route::any('/authToken', [app\api\controller\AuthTokenController::class, 'index']);
|
||||
Route::post('/user/login', [app\api\controller\UserController::class, 'login']);
|
||||
Route::post('/user/register', [app\api\controller\UserController::class, 'register']);
|
||||
Route::post('/user/logout', [app\api\controller\UserController::class, 'logout']);
|
||||
})->middleware([CheckApiAuthMiddleware::class]);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
return [
|
||||
// 默认缓存驱动
|
||||
'default' => env('CACHE_MODE', 'file'),
|
||||
// 默认缓存驱动(API 用户缓存依赖 Redis,建议设为 redis 并配置 REDIS_*)
|
||||
'default' => env('CACHE_MODE', 'redis'),
|
||||
// 缓存连接方式配置
|
||||
'stores' => [
|
||||
// redis缓存
|
||||
|
||||
Reference in New Issue
Block a user