外观
使用与配置
应用实现 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-user | false | 选择是否在当前 Servlet request attribute 中缓存当前用户与权限用户 |
own.security.login-verification | false | ParentGetUtil.isLoginVerification() 的返回值;控制 Base 取用户方法中的登录检查 |
要求身份的应用应显式配置:
yaml
own:
auth:
cache-session-user: true
security:
login-verification: truegetLoginUser() / getPermissionUser() 默认请求校验,但 Provider 路径还受 login-verification 控制。开启后未登录抛出 U0009;关闭时可以取得未登录默认对象,其用户 ID 为 -1,调用方不能据“返回非 null”认定已登录。
getLoginUser(false) 等重载显式跳过该校验;SessionUserUtil.checkLogin() 则直接检查登录状态,不因配置为 false 就自动通过。自定义 SessionUserProvider 时,策略由该 Provider 决定,未必读取这项属性。
该属性来自共享 SecurityProperty。其中 excludePathPatterns、permission 等其他字段不是 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 只支持 cookie、header、parameter,区分大小写;未知或 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 时创建 |
| UserUtil、LoginInfoUtil | 分别缺少同类型 Bean 时创建,依赖当前请求代理 |
| UserStatusSpringHook | 缺少同类型 Bean 时创建,收集 UserStatusHook 列表 |
一般只实现 AuthenticationLoginUser,沿用其余适配器,无需扫描整个 com.own。自定义 SessionUserProvider 会使 ParentGetUtil 的默认创建退让;SessionUserUtil 此时走自定义 Provider,其他 Authentication Bean 仍可能存在。
多个身份来源或父适配器并存时应明确唯一候选。ParentGetUtil.INSTANCE 和 Base Holder 都保存静态引用,不是按请求或多个应用上下文动态选择的机制。非 Servlet 环境不自动装配这条链,需要应用按执行环境显式提供身份;权限 Store 服务的装配条件则见下一页。