将JSF前缀映射更改为后缀会强制我重新应用于CSS背景图像的映射

14

我多年来一直使用前缀映射,但决定切换到后缀映射,只是为了从url中去掉/faces。在深入之前,我只是想确认我正在朝着正确的方向走,因为有一些意外情况发生。我从以下内容进行了更改:

<servlet-mapping>
    <servlet-name>FacesServlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
</servlet-mapping>

变成这样:

<servlet-mapping>
    <servlet-name>FacesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

我看到所有通过FacesServlet的内容都加上了.xhtml,所以浏览器请求的是background.png.xhtmlstyle.css.xhtml文件,这是正确的吗?我想这被称为后缀映射,但我认为它看起来有点不整洁,我试图说服自己这是正确的做法。

在我的CSS文件中,当引用URI时也必须添加.xhtml

background-image: url(images/background.png.xhtml);

然后我看到了BalusC的一篇帖子,提供了一个解决方案,可以防止在不经过FacesServlet的情况下下载资源:

<security-constraint>
    <display-name>Restrict raw XHTML docs</display-name>
    <web-resource-collection>
        <web-resource-name>XHTML</web-resource-name>
        <url-pattern>*.xhtml</url-pattern>
    </web-resource-collection>
    <auth-constraint/>
</security-constraint>

只有当我添加这个后,页面上才会加载真正的 .xhtml 文件,所有其他资源(尽管已添加了.xhtml)都不显示。

我想知道的是:

  1. .xhtml 添加到所有内容中是否正常(如果这是最愚蠢的问题,请原谅我)

  2. 为什么“限制原始xhtml文档”的安全约束会阻止CSS、JavaScript和图像等资源的加载?

感谢任何反馈。我正在 Glassfish 3.1 上使用 Mojarra 2.1.2。

1个回答

18

那么我看到一切通过FacesServlet传递的内容都附加了 .xhtml,所以浏览器正在请求 .png.xhtml 文件、.css.xhtml 文件 - 这是对的吗?

这只适用于由<h:outputStylesheet><h:outputScript>包含的资源。这与URL映射的更改无关。这与从JSF 1.x到JSF 2.x的更改以及从<link rel =“stylesheet”><script>到上述JSF2标签的更改有关。

对于您自己的脚本、样式表和其他静态内容,这些内容将被提供给公共Web内容,您不应手动添加.xhtml扩展名。您不需要更改现有静态资源的任何内容。

仅针对CSS背景图像和CSS文件中使用url()引用的其他内容(使用<h:outputStylesheet>标记包含,因此不适用于<link rel =“stylesheet”>),您需要更改url()位置,以使其由EL动态解析。您需要使用以下语法:

body {
    background-image: url("#{resource['libraryname:path/to/image.png']}");
}

假设您有以下的/resources文件夹结构:

WebContent
 |-- META-INF
 |-- resources
 |    `-- default
 |         |-- images
 |         |    `-- background.png
 |         `-- css
 |              `-- style.css
 |-- WEB-INF
 `-- test.xhtml

假设您在以下情况下将style.css包含在test.xhtml中:

<h:outputStylesheet library="default" name="css/style.css" />

那么你应该按照以下方式定义背景图片的URL

body {
    background-image: url("#{resource['default:images/background.png']}");
}

或者当你依赖默认库时,因此你没有使用library,那么它应该像这样:

WebContent
 |-- META-INF
 |-- resources
 |    |-- images
 |    |    `-- background.png
 |    `-- css
 |         `-- style.css
 |-- WEB-INF
 `-- test.xhtml

test.xhtml:

<h:outputStylesheet name="css/style.css" />

style.css:

body {
    background-image: url("#{resource['images/background.png']}");
}
就安全约束而言,在您已经使用*.xhtml映射时,它是不需要的。安全约束旨在防止最终用户在FacesServlet映射到除*.xhtml之外的模式时查看原始XHTML源代码。如果映射为/faces/*,最终用户只需从URL中删除/faces部分,如果映射为*.jsf,则只需将.jsf重命名为.xhtml即可查看XHTML源代码。因为您已经使用*.xhtml映射,这使得通过URL黑客攻击查看原始XHTML源代码变得完全不可能,所以去掉安全约束只会使情况变得更糟。

我创建了一个 NetBeans JSF 模板项目,配置 *.xhtml 后缀映射,在 index.xhtml 文件中添加了 <h:outputStylesheet name="styles.css"/>,然后我看到浏览器请求 styles.css.xhtml。没有过滤器、资源管理器或容器安全,这似乎就是它的工作方式。我每周都使用 JSF 7 天,但却无法使最简单的应用程序能够使用 *.faces 后缀。对之前评论的更正,没有得到 login.xhtml.xhtml,只有 login.xhtml,但所有非 .xhtml (js、css 等) 都附加了 .xhtml 后缀。 - Oversteer
使用 .xhtml 可以工作,但在样式表中的 url() 引用中必须添加 .xhtml 的后缀名,有点不方便。通过一个由 NetBeans 生成的包含 <h:outputStylesheet name="styles.css"/> 的 10 行 web 项目进行验证。使用 chrome 开发工具(及 NB http 监视器),我清楚地看到了对 styles.css.xhtml 的 GET 请求。我只是担心这会掩盖一个更严重的配置错误,如果您对此感到惊讶,那么我一定做错了些什么。这可能是一个 Glassfish 配置问题,我得检查 domain.xml 文件。 - Oversteer
关于这个问题,我的最终评论是:只有在使用h:outputStylesheet加载时才会出现styles.css.xhtml的问题,而不是使用<link type="text/css" rel="stylesheet" href="..."/>。我已经记录了这个问题http://java.net/jira/browse/JAVASERVERFACES-2153。 - Oversteer
啊,现在我终于明白你的问题了。当你使用<h:outputStylesheet>来包含CSS而不是<link>时,你需要改变所有引用的CSS背景图片的URL以匹配FacesServlet的URL模式,以便加载它们。这与你是否使用前缀或后缀映射无关!请查看更新后的答案。 - BalusC
他只是没有明确具体的问题,所以我忽略了他。他似乎在暗示JSF不应该给资源加后缀,但这是不正确的,正如我在答案中所述。如果他有具体的问题,他应该发布一个单独的问题来解决。 - BalusC
显示剩余13条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接