主题
移动应用端 API 开发指南
CatchAdmin 专业版已提供完整的后台管理系统,现新增移动应用端开发解决方案。app
应用端专为前端移动应用和 Web 应用提供标准化 API 接口服务,支持快速构建现代化应用程序。核心功能包括
- 基于
JWT
的用户认证 - 统一的枚举管理
- 统一的响应处理
- 统一异常渲染处理
- 身份认证中间件
为了帮助开发者快速掌握 CatchAdmin 专业版 app
应用端的标准化开发架构,本文将详细介绍每个功能模块的实现方法和最佳实践,建议在开始 API 开发前完整阅读
INFO
移动应用端 API 路由统一使用 api/app
前缀,可通过 php artisan route:list | grep api/app
命令查看所有可用接口
WARNING
移动应用端采用独立架构设计,与后台管理系统在业务逻辑上完全分离,仅在数据模型层共享。应用端通过调用各模块的 Eloquent 模型来实现数据访问。
如需更规范的数据访问层管理,建议在 app
应用中引入仓库模式(Repository Pattern)。
JWT 用户认证系统
CatchAdmin 专业版移动应用端采用 JWT(JSON Web Token)作为身份认证解决方案。相比后台管理使用的 Laravel Sanctum,JWT 更适合移动端和分布式应用场景,主要优势包括
santum
一次身份正常需要查询两次,JWT
只有一次JWT
的 Claim 可以承载更多的信息,无需回表。sanctum
需要从数据库查询sanctum
只适合单体应用,JWT
兼容单体,并支持分布式架构
基于性能和扩展性考虑,在高并发移动应用场景下,JWT 认证方案具有明显的性能优势和更好的横向扩展能力,因此 CatchAdmin 专业版应用端选择 JWT 作为标准身份认证方案。
安装
CatchAdmin 专业版 3.2.0+ 版本内置 JWT 认证支持,无需额外配置。低于此版本需要手动安装 JWT 扩展包
WARNING
请确认 CatchAdmin 专业版版本:< 3.2.0 需要执行以下安装步骤,>= 3.2.0 版本可跳过此节。
shell
composer require "tymon/jwt-auth"
然后发布 jwt
配置文件
shell
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
再生成 jwt
密钥
shell
php artisan jwt:secret
JWT
配置请查看配置文件 config/jwt.php
路由
移动应用端当前提供基础的用户认证 API 接口:登录
和登出
。完整路由配置位于 routes/api.php
文件
php
Route::prefix('app')->group(function (){
// 登录
Route::post('login', [AuthController::class, 'login']);
// 登出
Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:app');
});
auth 配置
在 config/auth.php
配置文件中,针对移动应用端的身份认证守卫(Guard)配置如下
php
return [
'guards' => [
// 前台 app 接口认证
'app' => [
'driver' => 'jwt',
'provider' => 'app_users',
]
],
'providers' => [
// 前台用户模型
'app_users' => [
'driver' => 'eloquent',
'model' => \Modules\Member\Models\Members::class // 使用会员表
],
],
];
认证代码
移动应用端支持多种身份认证方式:密码登录
、微信小程序登录
、小程序手机号快捷登录
。认证控制器位于 app/Http/Controllers/AuthController.php
,基于 Laravel Auth 门面实现标准化身份验证流程
php
use App\Services\Auth\UserService;
class AuthController extends Controller
{
/**
* 登录
*
* @param Request $request
* @param UserService $service
* @return JsonResponse
*/
public function login(Request $request, UserService $service): JsonResponse
{
// 系统封装了 UserService 用于处理用户登录
$user = $service->setAdapterType($request->get('type'))->auth($request->all());
if (! $user) {
throw new UnauthorizedAccessException();
}
return $this->success($user);
}
/**
* @return JsonResponse
*/
public function logout(): JsonResponse
{
// 退出之后将 token 加入黑名单
$this->appGuard()->logout(true);
return ApiResponse::success();
}
}
用户认证服务的核心实现逻辑,请参考 app/Services/Auth/UserService.php
认证服务类
php
/* @var Login $loginAdapter */
$loginAdapter = app($this->getLoginAdapter($this->type));
if ($res = $loginAdapter->auth($params)) {
[$user, $token] = $res;
$user->rememberToken($token);
return $user->makeHidden([
'password', 'from', 'creator_id'
]);
}
return false;
对应的三种登录方式代码
php
// app/Services/Auth/PasswordLogin.php
// 自动识别登录账号类型:手机号格式则使用 mobile 字段,否则使用 username 字段
$field = preg_match('/^1[0123456789]\d{10}$/', $params['account']) ? 'mobile' : 'username';
// Auth 认证
$token = Auth::guard('app')->attempt([
$field => $params['account'],
'password' => $params['password'],
]);
if ($token) {
return [Auth::guard('app')->user(), $token];
}
return false;
php
// app/Services/Auth/WechatLogin.php
try {
// 通过微信小程序 code 换取 session_key 和 openid
$response = $this->getMiniAppApplication()->getUtils()->codeToSession($params['code']);
$user = $this->getAuthModel()->firstOrCreate([
'miniapp_openid' => $response['openid'],
],[
'username' => $params['username'],
'from' => 'miniprogram',
'miniapp_openid' => $response['openid'],
'avatar' => $this->storeAvatar(),
'mobile' => '',
'created_at' => time(),
'last_login_at' => time(),
'updated_at' => time(),
]);
if (! $user) {
return false;
}
return [$user, JWTAuth::fromUser($user)];
} catch (\Throwable $e) {
throw new UnauthorizedAccessException();
}
php
// app/Services/Auth/WechatByMobileLogin.php
try {
// 获取微信小程序用户的 openid
$openid = $this->getMiniAppOpenId($params['code']);
// 检查是否已存在该 openid 的用户记录
$user = $this->getAuthModel()->where('miniapp_openid', $openid)->first();
if ($user) {
$user->username = $params['username'];
$user->mobile = $this->getMiniAppUserMobile($params['phoneCode']);
$user->avatar = $this->storeAvatar();
$user->last_login_at = time();
$user->updated_at = time();
$user->save();
} else {
$user = $this->getAuthModel()->firstOrCreate([
'mobile' => $this->getMiniAppUserMobile($params['phoneCode']),
], [
'username' => $params['username'],
'from' => 'miniprogram',
'avatar' => $this->storeAvatar(),
'miniapp_openid' => $openid,
'created_at' => time(),
'last_login_at' => time(),
'updated_at' => time(),
]);
}
if (! $user) {
return false;
}
return [$user, JWTAuth::fromUser($user)];
} catch (\Throwable $e) {
throw new UnauthorizedAccessException();
}
API 认证中间件配置
移动应用端身份认证中间件实现位于 app/Http/Middleware/AuthMiddleware.php
,负责验证 JWT Token 有效性
php
class AuthMiddleware
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, string $guard): Response
{
if (! $request->bearerToken()) {
throw new TokenMissedException();
}
$user = Auth::guard($guard)->user();
if (! $user) {
throw new AuthenticationException();
}
return $next($request);
}
}
中间件别名
为简化中间件调用,为认证中间件配置别名。在 bootstrap/app.php
文件中注册中间件别名
php
// 在 bootstrap/app.php 文件中注册中间件别名
->withMiddleware(function (Middleware $middleware) {
//
$middleware->alias([
// 注册认证中间件别名,支持多种守卫:auth:app(移动端)、auth:web(后台)等
'auth' => AuthMiddleware::class
]);
})
认证中间件通过 Laravel Auth 门面实现多守卫支持,只需传入对应的守卫名称 $guard
参数。移动应用端需要身份认证的路由配置示例
php
// 使用 auth:app 中间件,指定使用移动应用端的 JWT 认证守卫
Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:app');
响应码枚举管理
移动应用端所有枚举类统一管理在 App\Enums
目录下,提供类型安全的常量定义。当前内置枚举包括
- Enum 枚举接口
- Code 项目自带的响应码枚举
WARNING
移动应用端开发规范:所有自定义枚举类必须实现 Enum
接口,确保代码的一致性和可维护性。
下面是 Code
枚举的具体实现,对于响应的数据的 code
可以根据实际需求重新修改
php
/**
* API 响应状态码枚举 - 统一管理移动应用端响应代码
*/
enum Code:int implements Enum
{
case SUCCESS = 10000;
case FAILED = 10001;
case LOGIN_FAILED = 10002;
case AUTH_EXCEPTION = 10003;
case TOKEN_EXPIRED = 10004;
case TOKEN_INVALID = 10005;
case TOKEN_BLACKLIST = 10006;
case TOKEN_MISSED = 10007;
/**
* @return string
*/
public function message(): string
{
return match ($this) {
self::SUCCESS => 'success',
self::FAILED => 'failed',
self::LOGIN_FAILED => '登录失败',
self::AUTH_EXCEPTION => '认证失败',
self::TOKEN_EXPIRED => 'token 过期',
self::TOKEN_INVALID => 'token 无效',
self::TOKEN_BLACKLIST => 'token 黑名单',
self::TOKEN_MISSED => 'token 丢失',
};
}
/**
* @param mixed $value
* @return bool
*/
public function equal(mixed $value): bool
{
return $this->value === $value;
}
}
API 响应格式规范
移动应用端提供统一的 API 响应格式处理类,确保客户端接收到一致的数据结构。可根据项目需求自定义响应格式
php
/**
* 移动应用端统一 API 响应处理类
* 确保所有接口返回一致的数据格式
*/
class ApiResponse
{
/**
* 成功响应 - 标准成功数据格式
*/
public static function success(mixed $data = [], string $message = 'success', Code $code = Code::SUCCESS): JsonResponse
{
return response()->json([
'code' => $code->value,
'message' => $message,
'data' => $data,
]);
}
/**
* 错误响应 - 标准错误信息格式
*/
public static function error(string $message = 'api error', int|Code $code = Code::FAILED): JsonResponse
{
return response()->json([
'code' => $code instanceof Enum ? $code->value : $code,
'message' => $message,
]);
}
/**
* 分页响应 - 列表数据分页格式
*/
public static function paginate(LengthAwarePaginator $paginator, string $message = 'success', Code $code = Code::SUCCESS): JsonResponse
{
return response()->json([
'code' => $code->value,
'message' => $message,
'data' => $paginator->items(),
'total' => $paginator->total(),
'limit' => $paginator->perPage(),
'page' => $paginator->currentPage(),
]);
}
}
API 异常处理机制
移动应用端在 App\Exceptions
目录下提供完整的异常处理机制,支持类型化异常管理和统一错误响应。内置异常类型包括
AuthenticationException
身份认证异常FailedException
通用的失败异常TokenMissedException
token 修饰异常UnauthorizedAccessException
登录授权异常
为实现移动应用端异常的统一处理和响应格式标准化,所有自定义异常类必须继承 ApiAppException
基类
php
abstract class ApiAppException extends HttpException
{
//
public function __construct(
string $message = '',
Code $code = Code::FAILED
) {
// 异常所有的 code 都使用枚举值,那么只需要维护 Code 枚举类就可以了
if ($this->code instanceof Enum) {
$code = $this->code;
$this->message = $this->code->message();
}
parent::__construct(
$this->statusCode(),
$message ?: $this->message,
null,
[],
$code->value
);
}
/**
* @return int
*/
protected function statusCode(): int
{
return 500;
}
}
例如 AuthenticationException
异常,只需要这么定义就可以了
php
use App\Enums\Code;
class AuthenticationException extends ApiAppException
{
protected $code = Code::AUTH_EXCEPTION;
}
通过枚举类统一管理异常代码和错误信息,实现了异常处理的类型安全和维护便利性。
统一异常处理
为确保移动应用端获得一致的 JSON 格式错误响应,需要配置全局异常处理器。在 bootstrap/app.php
文件的 withExceptions
方法中配置
php
->withExceptions(function (Exceptions $exceptions) {
$exceptions->render(function (Throwable $exception, Request $request) {
// 渲染 app 异常,返回错误信息
if ($exception instanceof ApiAppException) {
return ApiResponse::error($exception->getMessage(), $exception->getCode());
}
// 其他系统异常自行处理, 请根据项目实际情况进行处理
// 如果路由前缀使用 api/app 则返回 api app 异常
if ($request->route()->prefix('api/app')) {
return ApiResponse::error($exception->getMessage(), $exception->getCode());
}
});
})
API 路由组织结构
移动应用端 API 路由按照认证需求进行分组管理,将公开接口和需要身份认证的接口分别组织。在 routes/api.php
中按以下结构配置
php
// 移动应用端 API 路由组织 - 按认证需求分组管理
Route::prefix('app')->group(function (){
// 公开接口:无需身份认证即可访问
Route::post('login', [AuthController::class, 'login']);
// 私有接口:需要 JWT Token 认证才能访问
Route::middleware('auth:app')->group(function () {
Route::post('logout', [AuthController::class, 'logout']);
// 在此添加其他需要认证的 API 接口
});
});
至此,CatchAdmin 专业版移动应用端开发框架的核心功能已介绍完毕。基于这套标准化的 API 开发架构,您可以快速构建安全、高效的移动应用后端服务。