登录中心功能开发

This commit is contained in:
mzl
2025-07-07 18:34:21 +08:00
parent 642c25503d
commit 4ddf4921b2
13 changed files with 372 additions and 7 deletions
+10
View File
@@ -8,6 +8,16 @@ use support\Request;
class AuthController extends BaseController
{
public function feishuScope(Request $request)
{
try {
$result = (new AuthService())->feishuAuthorize($request->corp_abbr, $request->system_code);
return $this->success($result);
} catch (\Throwable $e) {
return $this->error($e->getMessage());
}
}
public function login(Request $request)
{
-2
View File
@@ -2,8 +2,6 @@
namespace app\common\controller;
use support\Request;
use support\Response;
use support\exception\BusinessException;
use app\common\traits\ResponseTrait;
use think\Validate;
+52
View File
@@ -2,6 +2,8 @@
namespace app\common\logic;
use app\common\model\Corp;
use app\common\model\CorpFeishuApp;
use app\common\model\UserTokenLog;
use app\common\model\Systems;
use app\common\model\User;
@@ -375,6 +377,30 @@ class AuthLogic
return $system;
}
/**
* 公司验证
*/
private function validateCorp(string $corpAbbr)
{
$corp = Corp::where('abbr', $corpAbbr)->first();
if (!$corp) {
throw new BusinessException('公司不存在', 403);
}
return $corp;
}
/**
* 飞书应用信息
*/
private function validateFeishuApp(int $corpId, string $systemCode)
{
$feishuAppInfo = CorpFeishuApp::where('corp_id', $corpId)->where('system_code', $systemCode)->first();
if (!$feishuAppInfo) {
throw new BusinessException('飞书应用不存在', 403);
}
return $feishuAppInfo;
}
/**
* 用户系统权限校验
*/
@@ -450,6 +476,16 @@ class AuthLogic
*/
private function getFeishuUserInfo(string $code)
{
// // 获取凭证
// $certificate = certificate($param['state']);
// // 获取token
// $class = new Feishu($certificate['appId'], $certificate['appSecre_s'], $param['state']);
// $userAccessToken = $class->userAccessToken($param['code'], $certificate['rUrl']);
// // 获取用户信息
// $rst = $class->userInfo($userAccessToken['access_token']);
// if ($rst['code'] != 0) {
// throw new BusinessException('授权失败,请重试');
// }
// 实际实现需要调用飞书 API
return [
'user_id' => 'feishu_user_123',
@@ -472,4 +508,20 @@ class AuthLogic
}
return $user;
}
/**
* 飞书应用信息
*/
public function feishuAppInfo(string $corpAbbr, string $systemCode)
{
$corpInfo = $this->validateCorp($corpAbbr);
$fsAppInfo = $this->validateFeishuApp($corpInfo->id, $systemCode);
return [
'app_id' => $fsAppInfo->app_id,
'app_secret' => $fsAppInfo->app_secret,
'r_url' => $fsAppInfo->r_url,
'scope' => $fsAppInfo->scopes,
'state' => $fsAppInfo->state
];
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace app\common\model;
use support\Model;
/**
* corp 企业-信息
* @property integer $id ID(主键)
* @property string $name 名称
* @property string $abbr 缩写
* @property string $tenant_key 飞书企业标识
* @property integer $sort 排序
* @property integer $status 状态
* @property integer $created_at 创建时间
* @property integer $updated_at 更新时间
*/
class Corp extends Model
{
/**
* The connection name for the model.
*
* @var string|null
*/
protected $connection = 'mysql';
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'corp';
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'id';
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = true;
}
+56
View File
@@ -0,0 +1,56 @@
<?php
namespace app\common\model;
use support\Model;
/**
* corp_feishu_app 企业-飞书应用
* @property integer $id ID(主键)
* @property integer $corp_id 公司ID
* @property string $name 名称
* @property string $tenant_key 企业标识
* @property string $app_id 应用ID
* @property string $app_secret 应用秘钥
* @property string $base_uri 基础域
* @property string $r_url 授权地址
* @property string $scopes 授权范围
* @property string $state 携带参数
* @property string $system_code 绑定系统码
* @property integer $sort 排序
* @property integer $status 状态
* @property integer $created_at 创建时间
* @property integer $updated_at 更新时间
*/
class CorpFeishuApp extends Model
{
/**
* The connection name for the model.
*
* @var string|null
*/
protected $connection = 'mysql';
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'corp_feishu_app';
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'id';
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = true;
}
+9
View File
@@ -4,11 +4,20 @@ namespace app\common\service;
use app\common\logic\AuthLogic;
use app\common\model\User;
use app\common\utils\Feishu;
use support\Db;
class AuthService
{
/**
* 飞书授权
*/
public function feishuAuthorize(string $corpAbbr, string $systemCcode)
{
return (new AuthLogic())->feishuAppInfo($corpAbbr, $systemCcode);
}
/**
* 登录,支持多类型
*/
+118
View File
@@ -0,0 +1,118 @@
<?php
namespace app\common\service;
use app\common\model\Corp;
use app\common\model\Systems;
use support\Redis;
use support\exception\BusinessException;
class BasicDataService
{
/**
* 检查并缓存独立的基础参数
*/
public function checkAndCacheBaseParams($loginType, $systemCode, $corpAbbr)
{
// 构造缓存键
$loginTypeKey = 'login_type_' . $loginType;
$systemCodeKey = 'system_code_' . $systemCode;
$corpAbbrKey = 'corp_abbr_' . $corpAbbr;
// 检查缓存中是否有登录类型参数
if (!$this->checkParamInCache($loginTypeKey, $loginType)) {
// 如果 Redis 没有缓存,执行数据库查询并存入缓存
$this->cacheLoginType($loginTypeKey, $loginType);
}
// 检查缓存中是否有系统码参数
if (!$this->checkParamInCache($systemCodeKey, $systemCode)) {
// 如果 Redis 没有缓存,执行数据库查询并存入缓存
$this->cacheSystemCode($systemCodeKey, $systemCode);
}
// 检查缓存中是否有公司标识参数
if (!$this->checkParamInCache($corpAbbrKey, $corpAbbr)) {
// 如果 Redis 没有缓存,执行数据库查询并存入缓存
$this->cacheCorpAbbr($corpAbbrKey, $corpAbbr);
}
return true;
}
/**
* 检查参数是否在 Redis 缓存中
*/
private function checkParamInCache($cacheKey, $param)
{
return Redis::get($cacheKey) === $param;
}
/**
* 缓存登录类型
*/
private function cacheLoginType($cacheKey, $loginType)
{
// 假设我们从数据库或其他来源验证 loginType 的合法性
if (!$this->validateLoginType($loginType)) {
throw new BusinessException('无效的登录方式');
}
// 存入缓存,缓存有效期可以根据需求调整
Redis::setex($cacheKey, 3600, $loginType); // 1小时有效期
}
/**
* 缓存系统码
*/
private function cacheSystemCode($cacheKey, $systemCode)
{
// 假设我们从数据库或其他来源验证 systemCode 的合法性
if (!$this->validateSystemCode($systemCode)) {
throw new BusinessException('无效的系统码');
}
// 存入缓存,缓存有效期可以根据需求调整
Redis::setex($cacheKey, 3600, $systemCode); // 1小时有效期
}
/**
* 缓存公司标识
*/
private function cacheCorpAbbr($cacheKey, $corpAbbr)
{
// 假设我们从数据库或其他来源验证 corpAbbr 的合法性
if (!$this->validateCorpAbbr($corpAbbr)) {
throw new BusinessException('无效的公司标识');
}
// 存入缓存,缓存有效期可以根据需求调整
Redis::setex($cacheKey, 3600, $corpAbbr); // 1小时有效期
}
/**
* 验证登录方式
*/
private function validateLoginType($loginType)
{
// 假设这里是验证登录方式的具体逻辑
return in_array($loginType, ['upwd', 'feishu', 'qrcode']);
}
/**
* 验证系统码
*/
private function validateSystemCode($systemCode)
{
// 假设这里是验证系统码的具体逻辑
$system = Systems::where('code', $systemCode)->first();
return $system !== null;
}
/**
* 验证公司标识
*/
private function validateCorpAbbr($corpAbbr)
{
// 假设这里是验证公司标识的具体逻辑
$company = Corp::where('abbr', $corpAbbr)->first();
return $company !== null;
}
}
+2 -2
View File
@@ -19,7 +19,7 @@ trait ResponseTrait
public function success(
$data = [],
string $message = '请求成功',
int $code = 0,
int $code = 200,
int $httpStatus = 200,
array $header = ['Content-Type' => 'application/json']
): Response {
@@ -38,7 +38,7 @@ trait ResponseTrait
*/
public function error(
string $message = '请求失败',
int $code = 1,
int $code = 400,
int $httpStatus = 400,
$data = [],
array $header = ['Content-Type' => 'application/json']
+15 -2
View File
@@ -2,6 +2,7 @@
namespace app\common\validate;
use app\common\model\Corp;
use app\common\model\Systems;
use app\common\model\User;
use think\Validate;
@@ -17,7 +18,8 @@ class UserValidate extends Validate
'phone' => 'checkMobile|checkPhoneUnique',
'email' => 'email|checkEmailUnique',
'login_type' => 'require|in:upwd,feishu,qrcode',
'system_code' => 'require|checkSystemCode'
'system_code' => 'require|checkSystemCode',
'corp_abbr' => 'require|checkCorpAbbr',
];
protected $message = [
@@ -40,12 +42,15 @@ class UserValidate extends Validate
'login_type.require' => '请选择登录方式',
'login_type.in' => '登录方式不支持',
'system_code.require' => '系统码不能为空',
'system_code.checkSystemCode' => '系统码不存在或不合法'
'system_code.checkSystemCode' => '系统码不存在或不合法',
'corp_abbr.require' => '公司标识不能为空',
'corp_abbr.checkCorpAbbr' => '公司标识不存在或不合法'
];
protected $scene = [
'upwd_register' => ['name', 'account', 'password', 'confirm_password', 'login_type', 'system_code'],
'upwd_login' => ['account', 'password', 'login_type', 'system_code'],
'feishu_auth' => ['corp_abbr', 'system_code', 'login_type']
];
/**
@@ -129,4 +134,12 @@ class UserValidate extends Validate
{
return Systems::where('code', $value)->exists();
}
/**
* 验证 corp_abbr 企业标识是否存在
*/
protected function checkCorpAbbr($value, $rule, $data, $field)
{
return Corp::where('abbr', $value)->exists();
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace app\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
class AccessControl implements MiddlewareInterface
{
public function process(Request $request, callable $handler) : Response
{
// 如果是options请求则返回一个空响应,否则继续向洋葱芯穿越,并得到一个响应
$response = $request->method() == 'OPTIONS' ? response('') : $handler($request);
// 给响应添加跨域相关的http头
$response->withHeaders([
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Origin' => $request->header('origin', '*'),
'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
]);
return $response;
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace app\middleware;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
use app\common\service\BasicDataService;
class BasicDataMiddleware implements MiddlewareInterface
{
public function process(Request $request, callable $next): Response
{
try {
$loginType = $request->header('login_type');
$systemCode = $request->header('system_code');
$corpAbbr = $request->header('corp_abbr');
$basicDataService = new BasicDataService();
if ($basicDataService->checkAndCacheBaseParams($loginType, $systemCode, $corpAbbr)) {
$request->login_type = $loginType;
$request->system_code = $systemCode;
$request->corp_abbr = $corpAbbr;
}
return $next($request);
} catch (\Throwable $th) {
throw $th;
}
}
}
+5 -1
View File
@@ -12,4 +12,8 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
return [];
return [
'' => [
\app\middleware\BasicDataMiddleware::class
]
];
+1
View File
@@ -30,5 +30,6 @@ Route::group('/common', function () {
Route::group('/auth', function () {
Route::post('/login', [app\common\controller\AuthController::class, 'login']);
Route::post('/register', [app\common\controller\AuthController::class, 'register']);
Route::post('/feishu/scope', [app\common\controller\AuthController::class, 'feishuScope']);
});
});