Spring Security登出h:link报错:无法匹配导航规则,求根源及解决
问题分析与解决方案
为啥<h:link>会报错?
你推测的完全正确——<h:link>是绑定JSF导航规则的组件,它的outcome属性不是直接生成URL,而是先去匹配JSF的导航规则(包括检查是否存在对应的视图文件,比如logout.xhtml),只有找到合法的导航目标后,才会生成有效链接。
而你的Spring Security登出地址/logout是个非JSF视图的后端端点(由Spring Security处理,没有对应的logout.xhtml文件),所以JSF判定这个outcome找不到匹配的导航规则,直接把链接禁用了,就出现了你看到的错误:
This link is disabled because a navigation case could not be matched.
对比其他能正常工作的方式:
- 表单提交的方式是直接通过
action把请求发到/logout,完全绕过了JSF的导航规则校验,所以Spring Security能正常处理。 <h:outputLink>是纯粹生成HTML的<a>标签,value属性直接作为URL,不会经过JSF的导航校验,自然也没问题。
要是非得用<h:link>怎么解决?
有两种靠谱的思路:
方法1:直接用href属性(推荐)
从JSF 2.2开始,<h:link>支持直接指定href属性,这样就会跳过导航规则校验,直接生成目标URL:
<h:link value="Logout" href="#{request.contextPath}/logout" styleClass="nav-link" />
方法2:配置JSF导航规则映射
在faces-config.xml里加一条导航规则,把logout这个结果映射到你的登出端点,记得加上重定向:
<navigation-rule> <from-view-id>*</from-view-id> <navigation-case> <from-outcome>logout</from-outcome> <to-view-id>#{request.contextPath}/logout</to-view-id> <redirect /> </navigation-case> </navigation-rule>
之后你的<h:link>就可以这么写:
<h:link value="Logout" outcome="logout" styleClass="nav-link" />
<redirect />是关键,它会让JSF生成重定向到目标URL的链接,而不是尝试去渲染不存在的logout.xhtml。
总结一下
<h:link>的核心逻辑就是依赖JSF导航规则,所以当目标是非JSF的后端端点时,直接用outcome会触发校验失败。- 最简单的方案是用
<h:outputLink>或者给<h:link>加href属性;如果一定要用outcome,就配置导航规则并开启重定向。
内容的提问来源于stack exchange,提问作者Newbie
相关产品推荐
相关产品推荐

