I have a security constraint declared in web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>LoggedIn</web-resource-name>
<url-pattern>/screens/*</url-pattern>
</web-resource-collection>
<auth-constraint/>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
After logging in, when I make a GET request against the application I get the expected behavior e.g.
https://localhost:8443/Patrac/screens/user.xhtml –> results in access denied.
However, when I do a postback e.g.
<rich:menuItem submitMode="ajax" label="User" action="/screens/user"/>
I can view the screen. If I do a second identical postback, I get the access denied message. Each time I submit a postback the result alternates between displaying the screen and issuing a 403. The URL displayed in the browser alternates between the following:
https://localhost:8443/Patrac/screens/user.xhtml –> browser URL when access denied
https://localhost:8443/Patrac/public/403.xhtml –> browser URL when user screen is displayed
I understand the way the displayed browser URL in JSF lags behind the screen that is currently displayed, so that’s no mystery. But I don’t understand how I’m able to view the screen every other time the same postback is submitted. Again, GET requests are always denied.
EDIT :
I did try post-redirect-get and that made the strange behavior go away, as expected.
<rich:menuItem submitMode="ajax" label="User" action="/screens/user?faces-redirect=true"/>
However, I don’t want to do PRG every time and besides PRG doesn’t eliminate the security problem.
What am I missing here? Thanks for any insights!
The security constraint isn’t checked on forwards, but on requests. This is by design.
So you definitely need the PRG pattern or, better, normal GET links. It’ll instantly also make your webapp more SEO friendly and better bookmarkable. Using POST for page-to-page navigation is bad design anyway.
The “alternating behaviour” you’re seeing is because the forward isn’t checked, but any subsequent (postback) request on the same page is a fullworthy request and thus checked.