将参数发送到受限页面(无GET方法)

时间:2013-11-26 00:39:31

标签: jsf jsf-2 jaas

我的web.xml中有安全约束,因此“restrict”文件夹中的所有页面都受到保护,用户无法手动输入。

web.xml

<security-constraint>
    <display-name>restrict</display-name>
    <web-resource-collection>
        <web-resource-name>Restric Access</web-resource-name>
        <url-pattern>/restrict/*</url-pattern>
        <http-method>DELETE</http-method>
        <http-method>PUT</http-method>
        <http-method>HEAD</http-method>
        <http-method>OPTIONS</http-method>
        <http-method>TRACE</http-method>
        <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint />
</security-constraint>

在其中一个页面中,我想使用下面的导航规则将参数传递到另一页。

faces-config.xml

<navigation-rule>
    <from-view-id>/restrict/ranking.xhtml</from-view-id>
    <navigation-case>
        <from-outcome>editPerson</from-outcome>
        <to-view-id>/restrict/person.xhtml</to-view-id>
        <redirect include-view-params="true">
            <view-param>  
                <name>idPerson</name>  
                <value>#{ranking.person.idPerson}</value>  
            </view-param>           
        </redirect>
    </navigation-case>
</navigation-rule>

但这是不可能的,因为我限制了GET方法,我得到了"Access to the requested resource has been denied"。 那么,将参数传递给另一页的正确方法是什么?

  1. 使用@SessionScoped @ManagedBean设置会话变量,并在我在其他页面中使用时立即重置它?

  2. 使用FacesContext.getCurrentInstance()。getExternalContext()。getSessionMap()在我使用它们时立即添加和删除属性?

  3. 或者是什么?

  4. 我担心前两条建议,因为用户可能会在浏览器中打开很多标签来使用我的应用,因此所有标签只会有一个值。


    编辑:关于我收到的错误,控制台中没有堆栈跟踪我重定向的页面是这样的:

    HTTP Status 403 - Access to the requested resource has been denied
    type Status report
    message Access to the requested resource has been denied
    description Access to the specified resource has been forbidden.
    Apache Tomcat/7.0.47
    

    要解决此错误,我只需删除安全约束中的<http-method>GET</http-method>,然后我就可以手动输入页面。

1 个答案:

答案 0 :(得分:1)

你已经阻止了GET,所以<redirect>肯定无法正常工作,因为它实际上会创建一个新的GET请求。另请参阅What is the difference between redirect and navigation/forward and when to use what?

你能做什么?如果通过使用includes等有条件地将结果呈现在同一视图中(因此您可以继续使用相同的视图范围bean实例),那么您应该只执行不带重定向的POST导航。您可能已经确定导航将在创建新视图之前立即销毁绑定到当前视图的任何视图范围Bean。因此,不可能只在“当前”视图作用域中执行@ManagedProperty“先前”视图作用域bean。它会给你一个没有原始属性的全新实例。

但是,由于没有重定向的POST导航发生在非常相同的请求中,您实际上根本不需要在会话范围内传递数据,它可以正常工作通过请求范围。您只需要在与目标页面关联的视图范围bean的@PostConstruct中立即获取它。这些数据绝对不会在其他请求中共享。

基本上,流程可以如下所示(支持bean和属性名称只是根据目前提供的信息进行的有根据的猜测):

<h:dataTable value="#{ranking.persons}" var="person">
    <h:column>#{person.id}</h:column>
    <h:column>#{person.name}</h:column>
    <h:column>#{person.email}</h:column>
    <h:column><h:commandButton value="edit" action="#{ranking.editPerson(person)}" /></h:column>
</h:dataTable>
@ManagedBean(name="ranking")
@ViewScoped
public class RankingBacking implements Serializable {

    private List<Person> persons;

    public String editPerson(Person person) {
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        ec.getRequestMap().put("person", person);
        return "editPerson";
    }

    // ...
}
@ManagedBean(name="person")
@ViewScoped
public class PersonBacking implements Serializable {

    private Person current;

    @PostConstruct
    public void init() {
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
        current = (Person) ec.getRequestMap().get("person");
    }

    // ...
}
<h:outputText value="#{person.current.id}" />
<h:inputText value="#{person.current.name}" />
<h:inputText value="#{person.current.email}" />
...
<h:commandButton value="Save" ... />