配置MyFaces/JSF<protected-views>未生成javax.faces.Token的问题排查
javax.faces.Token触发ProtectedViewException排查 问题描述
我在faces-config.xml中配置了如下受保护视图:
<protected-views> <url-pattern>*.xhtml</url-pattern> <!-- 或更具体的URL规则 --> </protected-views>
但跳转至受保护页面时,URL中并未生成并附加javax.faces.Token参数(预期应为类似protected.xhtml?javax.faces.Token=xxx的形式),仅能看到jsessionid参数(例如localhost:8080/x/y/z;jsessionid=mVpYT),因此触发了org.apache.myfaces.lifecycle.RestoreViewExecutor.checkViewProtection(RestoreViewExecutor.java:396)中的javax.faces.application.ProtectedViewException,使用的MyFaces API和Core版本为2.3.10。
可能的遗漏配置及解决方法
启用客户端窗口模式为URL类型
MyFaces生成javax.faces.Token的前提是开启CLIENT_WINDOW_MODE为url,需在web.xml或faces-config.xml中添加以下配置:<context-param> <param-name>javax.faces.CLIENT_WINDOW_MODE</param-name> <param-value>url</param-value> </context-param>该配置会让JSF在生成受保护视图URL时自动附加客户端窗口Token。
确认视图保护功能未被禁用
检查是否存在禁用视图保护的配置,若有需改为启用(默认是启用状态):<context-param> <param-name>org.apache.myfaces.PROTECTED_VIEWS_ENABLED</param-name> <param-value>true</param-value> </context-param>使用JSF原生导航方式触发Token生成
javax.faces.Token仅在通过JSF规范的导航方式跳转时自动生成,包括:- 使用
<h:button>、<h:link>等JSF组件生成链接 - 通过JSF导航规则(
<navigation-case>)跳转 - 在Managed Bean中调用
ExternalContext.redirect()跳转(需先通过encodeProtectedURL处理URL)
若使用原生HTML
<a>标签或手动拼接URL跳转,需手动调用API生成带Token的URL:// 在Bean中生成受保护视图的URL FacesContext context = FacesContext.getCurrentInstance(); String protectedUrl = context.getExternalContext() .encodeProtectedURL("/your-protected-page.xhtml");- 使用
验证URL规则匹配正确性
确保跳转的URL完全匹配<protected-views>中的<url-pattern>规则。例如,若应用的JSF Servlet映射为/faces/*,则<url-pattern>需调整为/faces/*.xhtml,否则MyFaces不会将该URL识别为受保护视图,也就不会生成Token。确认Token参数名未被修改
检查是否存在自定义Token参数名的配置,若有需恢复为默认的javax.faces.Token:<context-param> <param-name>org.apache.myfaces.CLIENT_WINDOW_URL_PARAM_NAME</param-name> <param-value>javax.faces.Token</param-value> </context-param>
内容的提问来源于stack exchange,提问作者MacNord

