面向对象权限拦截的关键是拆解并串联“谁没登录”“该拦哪个接口”“拦后如何处理”三件事:用authenticationcontext封装主体识别,@requireauth显式标记受保护接口,切面委托authfailurehandler执行可配置、可测试的响应策略。

用面向对象思想做权限拦截,关键不是“写个类就完事”,而是把“谁没登录”“该拦哪个接口”“拦了之后怎么处理”这三件事拆清楚、串起来。核心不靠魔法注解堆砌,而靠责任明确的对象协作。
定义可识别的访问主体
先让系统能分辨“当前是谁”。不依赖全局静态变量或 ThreadLocal 隐式传递,而是封装成一个轻量对象:
- 创建 AuthenticationContext 类,含
getCurrentUser()和isAuthenticated()方法 - 在 WebFilter 或拦截器早期(如 Spring 的 OncePerRequestFilter)里解析 token 或 session,把用户信息塞进 Context 实例
- 后续所有切面、服务层都只通过这个 Context 问“当前有没有人”,不自己去拿 request、查 header
用注解标记需保护的边界
不一刀切拦全部接口,而是显式声明哪些方法需要认证:
- 自定义 @RequireAuth 注解,保留到运行时,支持类级和方法级
- 注解本身不带逻辑,只起标记作用,比如:
@RequireAuth(redirect = "/login") - 避免用泛化表达式(如
execution(* com.xxx.controller..*.*(..)))匹配所有 controller,容易误伤健康检查、登录注册等免检接口
切面里只做一件事:委托给策略对象
切面本身不写跳转、不拼 JSON、不查数据库,它只负责“发现要拦 → 找对的人来拦 → 把控制权交出去”:
- 切面类用
@Aspect @Component声明,切点定位@annotation(requireAuth) -
@Before方法中获取AuthenticationContext状态 - 若未认证,调用 AuthFailureHandler 接口的
handle(request, response, requireAuth) - 这个 handler 可以是重定向实现、JSON 错误响应实现、甚至弹窗提示实现——换策略不改切面
让未认证响应可配置、可测试
拦截后的动作不该硬编码在切面里,否则无法单元测试,也难适配前后端分离或 App 场景:
- 定义 AuthFailureHandler 接口,提供默认实现(如返回 401 JSON)
- 允许按注解参数动态选择行为:
@RequireAuth(type = "json")或@RequireAuth(type = "redirect") - 在测试中可 mock 这个 handler,验证切面是否在正确时机调用了它,而不必启动 HTTP 容器











