会员态鉴权
2026/10/26大约 2 分钟
会员态鉴权(MemberAuth)
基座 AuthCheck 中间件只校验 JWT 是否有效,不区分后台账号与前台会员。一方前台插件(am_plugin 体系)的控制器常把公开接口和会员接口放同一个控制器,需要自己定每个 action 的鉴权姿势。app\basic\MemberAuth trait 统一了会员态的解析口径与错误体,避免各插件各抄一份 Bearer 校验。
三种姿势
| 姿势 | 做法 |
|---|---|
| ① 公开 | action 写入 $noNeedLogin,不调用本 trait |
| ② 必登录(前台混合控制器推荐) | action 写入 $noNeedLogin 绕过 AuthCheck,方法首行 if ($resp = $this->requireMember($request)) return $resp; |
| ③ 纯管理接口 | action 不写白名单,由 AuthCheck 直接拦截,配合 #[Permission] 做 RBAC |
用法
namespace plugin\am_demo\app\controller;
use app\basic\BaseController;
use app\basic\MemberAuth;
use support\Request;
use support\Response;
class PostController extends BaseController
{
use MemberAuth;
// 姿势①:公开列表,携带合法 JWT 时个性化,匿名也放行
protected array $noNeedLogin = ['list'];
public function list(Request $request): Response
{
$this->optionalMember($request); // 解析身份,之后用 $this->sid() 判空
$sid = $this->sid(); // 未登录为空串
// ...
}
// 姿势②:必须登录(含后台账号)
#[Get('/mine')]
public function mine(Request $request): Response
{
if ($resp = $this->requireMember($request)) return $resp;
// 到这里一定已登录,$this->memberSid 可用
}
// 姿势②加强版:额外要求是有效会员(后台账号不放行)
#[Post('/comment')]
public function comment(Request $request): Response
{
if ($resp = $this->requireMember($request, memberOnly: true)) return $resp;
// ...
}
}方法一览
| 方法 | 作用 |
|---|---|
memberContext($request) | 解析并归一化当前身份(同请求内只解析一次),返回数组或 null |
requireMember($request, $memberOnly=false) | 要求登录;通过返回 null,失败返回统一响应(调用方直接 return) |
optionalMember($request) | 可选鉴权:有合法 JWT 则解析,无/失效按匿名放行 |
sid() | 当前主体 sid,未登录返回空串 |
isValidMember($sid) | 是否有效会员;会员中心未安装时恒 false,不致命 |
不硬依赖 am_member
memberOnly=true 才调用 MemberService,且用 class_exists 保护。会员中心未安装时按"非会员"处理,前台插件不因缺少 am_member 而报错。
错误体
身份解析统一走 getCurrentInfo()(tinywan/jwt 的 extend 段),与 AuthCheck 同口径,不自行解析 Authorization 头。失败返回业务形响应,前端 http 拦截器可识别:
- 未登录:
{ code: 401, msg: '请先登录', data: null },HTTP 401。 - 非会员访问会员内容:
{ code: 403, msg: '当前账号无权访问会员内容', data: null },HTTP 403。
