Question

I have a security constraint in my web.xml, so all pages inside "restrict" folder, are protected and the user can't enter them manually.

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>

In one of these pages, I'd like to pass parameters to the other page using the navigation rule below.

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>

But it's not possible because I restricted the GET method, and I'm getting "Access to the requested resource has been denied". So, what is the correct way to pass the parameter to the other page?

  1. Using a @SessionScoped @ManagedBean to set a session variable, and reseting it as soon as I use in the other page?

  2. Using FacesContext.getCurrentInstance().getExternalContext().getSessionMap() to add and remove attributes as soon as I use them?

  3. Or what?

I'm worried about the first 2 suggestions, because the user may open a lot of tabs in his browser to use my app, so there will be only one value for all tabs.


EDIT: About the error I'm getting, there's no stacktrace in the console the page that I'm redirected to is like this:

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

To solve this error, I could simply remove the <http-method>GET</http-method> in my security constraint, but then I would be able to enter the page manually.

Was it helpful?

Solution

You've blocked GET, so <redirect> is definitely not going to work as it actually creates a new GET request. See also What is the difference between redirect and navigation/forward and when to use what?

What can you do? If it's really not an option to conditionally render results in the very same view by using includes and such (so that you can just keep using the same view scoped bean instance), then you should just perform a POST navigation without a redirect. You probably already figured that a navigation will immediately destroy any view scoped beans tied to the current view before the new view is created. Hence it's not possible to just do a @ManagedProperty of "previous" view scoped bean in the "current" view scoped bean. It'll give you a brand new instance without the original properties.

However, as the POST navigation without a redirect happens all in the very same request, you actually don't need to pass the data along in the session scope at all, it would work as good via the request scope. You just have to grab it immediately in the @PostConstruct of the view scoped bean associated with the target page. This data is definitely not shared in other requests.

Basically the process can go as follows (backing bean and property names are just educated guesses based on information provided so far):

<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" ... />
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top