JSF - Spring 安全集成问题

Posted

技术标签:

【中文标题】JSF - Spring 安全集成问题【英文标题】:JSF - Spring Security Integration issue 【发布时间】:2012-02-28 22:20:38 【问题描述】:

Servlet 2.4+ API 允许我们在 <filter-mapping> 标记中使用 <dispatcher> 标记和 FORWARD 之类的值来拦截内部转发到其他资源的请求。对于一个 servlet 转发到另一个,spring 安全约束工作正常。

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>    

问题: 安全过滤器似乎不会使用 JSF Actions

拦截内部转发

JSF 似乎在使用 JSF 操作(导航案例)时将请求“转发”到目标视图(页面)。这会导致 URL 比页面的实际 URL 落后一步。

这样做的副作用是 spring 安全约束(与 URL 绑定)在下一个操作之前不会生效。

示例: 当前页面网址:http://host/myapp/page1.xhtml (page1.xhtml 有一个导航到受保护的 page2 的操作)

提交时,请求被提交到呈现 page2.xhtml 的服务器,但 URL 仍保持为 http://host/myapp/page1.xhtml。 Spring Security 不拦截和保护page2.xhtml

这可以通过指定以下内容来克服:

<navigation-case>
    <from-outcome>page2</from-outcome>
    <to-view-id>/page2.xhtml</to-view-id>
    <redirect/> <!--REDIRECT, INSTEAD OF FORWARD-->
</navigation-case>

重定向不是我们想要实现的方式。有没有更好的方法让 Spring Security 与 JSF 一起工作?

编辑:(spring config xml的相关sn-p)

<http use-expressions="true" once-per-request="false">
    <intercept-url pattern="/index.xhtml" access="permitAll" />
    <intercept-url pattern="/page1.xhtml" access="isAuthenticated()" />
    <intercept-url pattern="/page2.xhtml" access="hasRole('supervisor')" />
    <intercept-url pattern="/page3.xhtml" access="hasRole('teller')" />
    <form-login  login-page="/login.html" default-target-url="/page1.xhtml"/>
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="rod" password="rod" authorities="supervisor,  user" />
            <user name="dianne" password="dianne" authorities="teller, user" />
            <user name="scott" password="scott" authorities="supervisor" />
            <user name="peter" password="peter" authorities="user" />
        </user-service>
    </authentication-provider>
</authentication-manager>

【问题讨论】:

你也可以发布你的applicationContext.xml @Ravi 使用 appcontext.xml 中的内容编辑了问题有什么想法吗? 【参考方案1】:

来自horse's mouth(oracle 文档)

如果导航案例不使用重定向元素,新页面将呈现为对当前请求的响应,这意味着浏览器地址字段中的 URL 不会改变,并且它将包含上一页的地址。

这似乎意味着在 JSF 生命周期中没有“向前”发生到下一页......因此 Spring Security 永远无法处理这个问题。

【讨论】:

【参考方案2】:

默认情况下,FilterSecurityInterceptor 只会对每个请求执行一次,并且不会进行安全重新检查,除非 url 发生更改,但使用 JSP/JSF 转发页面将呈现为对当前请求的响应,并且浏览器中的url包含上一页的地址。因此,为此只需在 applicationContext 中的 http 元素中将每次请求属性设置为 false,从而强制重新检查安全性。

<http auto-config="true" use-expressions="true" once-per-request="false">

并在您的 web.xml 中的 springSecurityFilterChain 过滤器映射中添加转发调度程序

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

更多info

或者,您还可以通过将参数 faces-redirect=true 附加到结果中来启用页面重定向,如下所示:

<h:form>
    <h:commandButton action="page1?faces-redirect=true" value="Page1" />
</h:form>

但正如BalusC 所说,它不是使用 POST 进行页面导航的好习惯。始终使用

进行 GET
<h:link> or <h:button>

另见:

when-should-i-use-houtputlink-instead-of-hcommandlink

Post-Redirect-Get pattern

【讨论】:

以上是关于JSF - Spring 安全集成问题的主要内容,如果未能解决你的问题,请参考以下文章

我们可以集成 JSF 2.0 + Spring 4.2.X + Spring Security 4.2.X [重复]

Spring JSF 集成:如何在 JSF 托管 bean 中注入 Spring 组件/服务?

Spring Boot JSF 集成

JSF 与 Spring Security 的集成

Spring Security 4 和 JSF 2 集成

jsf spring安全用户信息