跳转到正文

使用与配置

应用实现 AuthenticationLoginUser 后,默认通过父适配器和 ParentGetUtil 接入 Base。业务通常使用 SessionUserUtil 读取身份,直接调用 SPI 会绕过其中的缓存、回退或登录校验环节。

身份适配链

默认读取路径是 SessionUserUtil → SessionUserProvider(ParentGetUtil)→ ParentAuthenticationLoginUser → AuthenticationLoginUser。Base 当前请求的覆盖身份优先于这条链,具体见请求覆盖规则

SPI 方法实现要求与默认行为
loginUser()必须实现;恢复当前请求的可信身份,未登录可返回 null 或未登录对象
permissionUser(BaseLoginUser)必须实现;为给定用户构造权限身份,不能假定参数一定已登录
无参数 permissionUser()接口默认先调用 loginUser(),再传给单参数方法
loginUser(Long userId)可选扩展,但接口默认返回 null;父适配器不接受该 null 结果
permissionUser(Long userId)同上;需要此功能时明确返回列表,无结果返回空列表

默认父适配器将当前用户的 null 替换为 DefaultLoginUser.DEFAULT,权限用户的 null 替换为 DefaultPermissionUser.DEFAULT;两者均未登录。按 ID 的两个列表查询没有默认列表回退,返回 null 会抛出“没有获取到对应的登录信息”。异常也不会被当成匿名结果吞掉。

这些按 ID 方法只查询身份,不会切换当前用户,也不自带访问目标用户的权限检查。它们是否表示在线设备、有效 Token 或其他身份集合,由应用实现决定。

缺少实现时

没有 AuthenticationLoginUser Bean 时,自动装配 DefaultNoAuthenticationLoginUser。它的四个主要方法全部抛出“请实现 AuthenticationLoginUser 接口”;因此应用可能正常启动,但首次读取身份才失败。

DefaultIgnoreAuthenticationLoginUser 是另一个可手工选择的类,不是默认 Bean。它返回未登录对象和空列表,不会建立有效身份;配合关闭登录检查时只能取得匿名模型,不能理解为已验证登录。

配置参考

完整属性默认值当前用途
own.auth.cache-session-userfalse选择是否在当前 Servlet request attribute 中缓存当前用户与权限用户
own.security.login-verificationfalseParentGetUtil.isLoginVerification() 的返回值;控制 Base 取用户方法中的登录检查

要求身份的应用应显式配置:

yaml
own:
  auth:
    cache-session-user: true
  security:
    login-verification: true

getLoginUser() / getPermissionUser() 默认请求校验,但 Provider 路径还受 login-verification 控制。开启后未登录抛出 U0009;关闭时可以取得未登录默认对象,其用户 ID 为 -1,调用方不能据“返回非 null”认定已登录。

getLoginUser(false) 等重载显式跳过该校验;SessionUserUtil.checkLogin() 则直接检查登录状态,不因配置为 false 就自动通过。自定义 SessionUserProvider 时,策略由该 Provider 决定,未必读取这项属性。

该属性来自共享 SecurityProperty。其中 excludePathPatternspermission 等其他字段不是 Authentication 的路由拦截配置;本模块不根据路径注册放行/拒绝规则,也不提供 own.auth.enabled 开关。

请求内缓存

cache-session-user=false 使用 ParentAuthenticationDefaultLoginUser,每次调用都委托身份来源。开启后使用 ParentAuthenticationDefaultCacheLoginUser

  • 当前用户缓存在 LOGIN_USER_CACHE_KEY,当前权限用户缓存在 PERMISSION_USER_CACHE_KEY 两个 request attribute 中。
  • 只有来源返回非 null 时才写入;null 回退对象不会缓存,来源主动返回未登录对象则会缓存。
  • 缓存按请求区分,不进入 HttpSession 或 Store,没有 TTL、跨请求复用或后台刷新。
  • 权限缓存键不包含传入用户。如果在同一请求中用不同用户调用父适配器的 permissionUser(user),可能仍取得先前缓存的权限对象。
  • 按 userId 的列表查询不经过这一缓存。

同一请求完成身份切换、退出或权限修改后,旧 attribute 仍可能存在。SessionUserUtil.clearLoginUser() 只删除 Base 的覆盖身份,不清除这两个缓存;UserStatusSpringHook.clear() 也不自动删除它们。需要请求中途重算时,可关闭缓存或自定义父适配器统一管理失效。

缓存保留对象引用,没有深拷贝或线程安全封装。异步任务可能与请求持有同一个 request,不应靠修改这些属性实现并发身份切换;上下文生命周期见 Base 异步任务

用户模型

DefaultLoginUser 的无参数构造器产生未登录对象;带 token、userId、userName、userType、client 的构造器直接设置 isLogin=true不会验证这些参数。复制构造器复制来源的登录状态和基础字段。

方法空值回退
token()null 或空字符串返回 -,不裁剪空白
userId()null 返回 -1L
userName()null 或空字符串返回 -
userType()null 返回 NORMAL
client()原样返回,未指定时为 null;覆盖了 Base 接口的 web 默认值
isLogin()返回构造时确定的状态,不随字段有效性重新判断

该类还有 Lombok 生成的 get 方法,返回底层字段而非上述回退值。直接序列化用户对象可能暴露 Token,也不能据 get 方法值推导接口回退规则;推荐像快速开始一样投影为专用响应 DTO。uuid()json() 继承自 Base 的行为见用户接口约定

DefaultPermissionUser 在此基础上增加角色集合和 MenuOperationFunction:无回调或传 null 时,操作判断始终 false。角色名并不会自动转换成操作权限,回调负责模块匹配及多个操作之间的 AND/OR 规则。

构造器接收角色集合时保留原引用,不复制;roleNameList() 也直接返回该集合。类提供角色 setter,静态 DEFAULT 也是共享对象,应用不要把匿名默认对象当作可修改的用户会话。身份和权限模型不应跨用户共用可变状态。

请求辅助工具

读取凭证

注入 UserUtil 后调用 getAuthToken(space, key):space 只支持 cookieheaderparameter,区分大小写;未知或 null 位置报“token获取位置异常”。Cookie 读取同名首项;Header 和请求参数读取对应值。没有请求上下文时返回 null。

它不会解析 Bearer 前缀、验证签名、查过期时间或撤销状态,也不默认约定某个请求头名。getLoginUser(token, function) 只拒绝 null Token,再调用函数;空白 Token 和函数结果仍需实现者检查。

记录登录流程的请求信息

LoginInfoUtil.type()account()code() 返回 LoginInfoFunction,用 set(String) / get() 读写 request attribute。键由进程初始化时的 UUID 派生,不是 HTTP 请求头名称。

这些信息只在当前请求中传递,不保存账号或密码到持久层,不触发登录流程,也不自动提供脱敏或加密。调用需要有效 Servlet 请求;敏感登录信息不要复制到普通响应或日志。

自动装配与覆盖

以下身份相关 Bean 仅由 Servlet 自动配置创建:

Bean默认创建条件
AuthenticationLoginUser缺少同接口 Bean 时提供报错占位实现
ParentAuthenticationLoginUser缺少同接口 Bean 时按请求缓存开关选择实现
ParentGetUtil缺少任何 SessionUserProvider Bean 时创建
UserUtilLoginInfoUtil分别缺少同类型 Bean 时创建,依赖当前请求代理
UserStatusSpringHook缺少同类型 Bean 时创建,收集 UserStatusHook 列表

一般只实现 AuthenticationLoginUser,沿用其余适配器,无需扫描整个 com.own。自定义 SessionUserProvider 会使 ParentGetUtil 的默认创建退让;SessionUserUtil 此时走自定义 Provider,其他 Authentication Bean 仍可能存在。

多个身份来源或父适配器并存时应明确唯一候选。ParentGetUtil.INSTANCE 和 Base Holder 都保存静态引用,不是按请求或多个应用上下文动态选择的机制。非 Servlet 环境不自动装配这条链,需要应用按执行环境显式提供身份;权限 Store 服务的装配条件则见下一页