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

Grails 3.2.5 REST Security插件双重认证问题求助

这问题我之前帮朋友排查过类似的,双重认证触发大概率是Spring Security过滤器链被重复执行了,结合你给的日志和Grails 3.2.5的环境,咱们一步步来定位解决:

1. 排查过滤器链的重复匹配配置

Grails Spring Security REST插件的过滤器链配置很容易踩坑——如果你的chainMap里有重叠的路径匹配规则,比如/**和/api/**同时存在,就会导致同一个请求被两次匹配过滤链,触发两次认证逻辑。
打开你的application.yml,找到Spring Security的chainMap配置,改成这样:

grails:
    plugin:
        springsecurity:
            filterChain:
                chainMap:
                    # 先匹配需要令牌验证的API路径
                    - pattern: '/api/**'
                      filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter'
                    # 再匹配其他路径,避免重复覆盖
                    - pattern: '/**'
                      filters: 'JOINED_FILTERS,-restTokenValidationFilter'

重点是给/**的过滤器链去掉restTokenValidationFilter,避免非API请求重复触发令牌验证,同时确保API路径只被匹配一次。

2. 检查HiddenHttpMethodFilter的干扰

从你的日志里看到HiddenHttpMethodFilter$HttpMethodRequestWrapper,这个过滤器在Grails里默认是启用的,它会把POST请求里的_method参数转换成对应HTTP方法,但有时候会导致请求被重新包装转发,触发第二次过滤链。
你可以先临时禁用它试试,在application.yml里加:

grails:
    web:
        hiddenmethod:
            enabled: false

如果禁用后双重认证消失了,那就是这个过滤器的锅,你可以调整它的执行顺序,让它在Spring Security过滤器之后运行,而不是之前。

3. 给自定义监听器加触发条件

你的AuthenticationSuccessListener现在是只要有AuthenticationSuccessEvent就触发,但令牌验证每次请求都会刷新安全上下文,也会触发这个事件。你可以修改监听器,只处理首次交互式认证或者判断认证是否是新生成的:

class CustomAuthenticationSuccessListener implements ApplicationListener<AuthenticationSuccessEvent> {

    @Override
    void onApplicationEvent(AuthenticationSuccessEvent event) {
        // 只处理真正的登录成功事件,而非每次令牌验证的上下文刷新
        if (event instanceof InteractiveAuthenticationSuccessEvent) {
            // 你的业务逻辑
            log.debug("处理首次登录成功事件: ${event.authentication.name}")
        }
        // 或者判断认证是否是刚创建的(比如不是从缓存/令牌中加载的)
        // if (!event.authentication.details?.class?.simpleName == "WebAuthenticationDetails") {
        //     // 处理逻辑
        // }
    }
}

4. 验证RestTokenValidationFilter的生效范围

确保令牌验证过滤器只对需要的路径生效,在application.yml里配置:

grails:
    plugin:
        springsecurity:
            rest:
                token:
                    validation:
                        active: true
                        # 只对API路径启用令牌验证
                        endpointUrl: '/api/**'

这样就不会让非API请求触发令牌验证,减少不必要的事件触发。

从你提供的日志片段来看,第一次过滤链已经完成了令牌验证,但没有进入GrailsDispatcherServlet,反而重新执行了过滤链,这大概率是某个过滤器转发了请求导致的,先试试上面的前两个方案,应该能解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:09:40