You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot如何从AuthorizationFailureEvent中获取Request URL

问题解答

异常出现的原因

Spring Security触发的AuthorizationFailureEvent的事件源类型,由授权校验的触发场景决定:

  • 当授权校验在Web过滤器链阶段执行(即你在HttpSecurity配置中定义的URL路径权限规则),此时事件源为FilterInvocation类型,可以强转后获取请求URL
  • 当授权校验在方法AOP代理阶段执行(即你在Controller/Service方法上添加了@PreAuthorize、@PreFilter等方法级安全注解),此时授权校验是在Spring AOP的方法调用流程中触发的,事件源为ReflectiveMethodInvocation类型,和过滤器链无关,强转为FilterInvocation自然会抛出ClassCastException。
    你当前的场景就是触发了方法级的授权校验,因此拿到的事件源不符合预期。

正确获取请求URL的方案

最通用的方案是直接从Spring Web的请求上下文持有者RequestContextHolder中获取当前请求对象,无需依赖事件源的类型,适配所有Web请求触发的授权事件:

修改后的代码示例

private void onAuthorizationFailureEvent(AuthorizationFailureEvent event) {
    Map<String, Object> data = new HashMap<>();
    data.put("type", event.getAccessDeniedException().getClass().getName());
    data.put("message", event.getAccessDeniedException().getMessage());
    // 从请求上下文获取请求URL,替代原来的从事件源获取的逻辑
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    if (attributes != null) {
        HttpServletRequest request = attributes.getRequest();
        data.put("requestUrl", request.getRequestURL().toString());
    }
    if (event.getAuthentication().getDetails() != null) {
        data.put("details",
          event.getAuthentication().getDetails());
    }
    publish(new AuditEvent(event.getAuthentication().getName(),
      AUTHORIZATION_FAILURE, data));
}

注意事项

  • 如果你的应用存在非Web请求触发的方法调用(比如定时任务、内部RPC调用),RequestContextHolder.getRequestAttributes()会返回null,上述代码中的空判断可以避免空指针异常。
  • 如果你不需要用到方法级安全校验,也可以将所有权限规则都统一配置到HttpSecurity的URL路径规则中,此时所有的授权失败事件源都为FilterInvocation,你原来的代码也可以正常运行,但该方案适配性不如第一种方案。

内容的提问来源于stack exchange,提问作者wxkevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 15:57:02